diff options
26 files changed, 9595 insertions, 9560 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 7de649b7d..fddb7676f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -165,6 +165,10 @@ nautilus_SOURCES = \ nautilus-error-reporting.h \ nautilus-file-management-properties.c \ nautilus-file-management-properties.h \ + nautilus-files-view.c \ + nautilus-files-view.h \ + nautilus-files-view-dnd.c \ + nautilus-files-view-dnd.h \ nautilus-floating-bar.c \ nautilus-floating-bar.h \ nautilus-freedesktop-dbus.c \ @@ -205,10 +209,6 @@ nautilus_SOURCES = \ nautilus-toolbar.h \ nautilus-trash-bar.c \ nautilus-trash-bar.h \ - nautilus-view.c \ - nautilus-view.h \ - nautilus-view-dnd.c \ - nautilus-view-dnd.h \ nautilus-window-slot.c \ nautilus-window-slot.h \ nautilus-window-slot-dnd.c \ diff --git a/src/nautilus-canvas-view-container.c b/src/nautilus-canvas-view-container.c index 141daef21..e9779bb56 100644 --- a/src/nautilus-canvas-view-container.c +++ b/src/nautilus-canvas-view-container.c @@ -346,13 +346,13 @@ fm_desktop_canvas_container_icons_compare (NautilusCanvasContainer *container, { NautilusFile *file_a; NautilusFile *file_b; - NautilusView *directory_view; + NautilusFilesView *directory_view; SortCategory category_a, category_b; file_a = (NautilusFile *) data_a; file_b = (NautilusFile *) data_b; - directory_view = NAUTILUS_VIEW (NAUTILUS_CANVAS_VIEW_CONTAINER (container)->view); + directory_view = NAUTILUS_FILES_VIEW (NAUTILUS_CANVAS_VIEW_CONTAINER (container)->view); g_return_val_if_fail (directory_view != NULL, 0); category_a = get_sort_category (file_a); @@ -361,7 +361,7 @@ fm_desktop_canvas_container_icons_compare (NautilusCanvasContainer *container, if (category_a == category_b) { return nautilus_file_compare_for_sort (file_a, file_b, NAUTILUS_FILE_SORT_BY_DISPLAY_NAME, - nautilus_view_should_sort_directories_first (directory_view), + nautilus_files_view_should_sort_directories_first (directory_view), FALSE); } diff --git a/src/nautilus-canvas-view.c b/src/nautilus-canvas-view.c index d1f3ec397..81cc2d80c 100644 --- a/src/nautilus-canvas-view.c +++ b/src/nautilus-canvas-view.c @@ -28,7 +28,7 @@ #include "nautilus-canvas-view-container.h" #include "nautilus-desktop-canvas-view.h" #include "nautilus-error-reporting.h" -#include "nautilus-view-dnd.h" +#include "nautilus-files-view-dnd.h" #include "nautilus-toolbar.h" #include <stdlib.h> @@ -158,7 +158,7 @@ static void nautilus_canvas_view_set_directory_sort_by (N const char *sort_by); 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 void nautilus_canvas_view_reveal_selection (NautilusFilesView *view); static const SortCriterion *get_sort_criterion_by_sort_type (NautilusFileSortType sort_type); static gboolean set_sort_reversed (NautilusCanvasView *canvas_view, gboolean new_value, @@ -166,9 +166,9 @@ static gboolean set_sort_reversed (NautilusC static void switch_to_manual_layout (NautilusCanvasView *view); static NautilusFileSortType get_default_sort_order (NautilusFile *file, gboolean *reversed); -static void nautilus_canvas_view_clear (NautilusView *view); +static void nautilus_canvas_view_clear (NautilusFilesView *view); -G_DEFINE_TYPE (NautilusCanvasView, nautilus_canvas_view, NAUTILUS_TYPE_VIEW); +G_DEFINE_TYPE (NautilusCanvasView, nautilus_canvas_view, NAUTILUS_TYPE_FILES_VIEW); static void nautilus_canvas_view_destroy (GtkWidget *object) @@ -177,7 +177,7 @@ nautilus_canvas_view_destroy (GtkWidget *object) canvas_view = NAUTILUS_CANVAS_VIEW (object); - nautilus_canvas_view_clear (NAUTILUS_VIEW (object)); + nautilus_canvas_view_clear (NAUTILUS_FILES_VIEW (object)); if (canvas_view->details->react_to_canvas_change_idle_id != 0) { g_source_remove (canvas_view->details->react_to_canvas_change_idle_id); @@ -273,7 +273,7 @@ real_set_sort_criterion (NautilusCanvasView *canvas_view, { NautilusFile *file; - file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (canvas_view)); + file = nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (canvas_view)); if (clear) { nautilus_file_set_metadata (file, @@ -350,7 +350,7 @@ unref_cover (NautilusCanvasIconData *data, gpointer callback_data) } static void -nautilus_canvas_view_clear (NautilusView *view) +nautilus_canvas_view_clear (NautilusFilesView *view) { NautilusCanvasContainer *canvas_container; GSList *file_list; @@ -370,26 +370,26 @@ nautilus_canvas_view_clear (NautilusView *view) } static void -nautilus_canvas_view_remove_file (NautilusView *view, NautilusFile *file, NautilusDirectory *directory) +nautilus_canvas_view_remove_file (NautilusFilesView *view, NautilusFile *file, NautilusDirectory *directory) { NautilusCanvasView *canvas_view; - /* This used to assert that 'directory == nautilus_view_get_model (view)', but that + /* This used to assert that 'directory == nautilus_files_view_get_model (view)', but that * resulted in a lot of crash reports (bug #352592). I don't see how that trace happens. * It seems that somehow we get a files_changed event sent to the view from a directory * that isn't the model, but the code disables the monitor and signal callback handlers when * changing directories. Maybe we can get some more information when this happens. * Further discussion in bug #368178. */ - if (directory != nautilus_view_get_model (view)) { + if (directory != nautilus_files_view_get_model (view)) { char *file_uri, *dir_uri, *model_uri; file_uri = nautilus_file_get_uri (file); dir_uri = nautilus_directory_get_uri (directory); - model_uri = nautilus_directory_get_uri (nautilus_view_get_model (view)); + model_uri = nautilus_directory_get_uri (nautilus_files_view_get_model (view)); g_warning ("nautilus_canvas_view_remove_file() - directory not canvas view model, shouldn't happen.\n" "file: %p:%s, dir: %p:%s, model: %p:%s, view loading: %d\n" "If you see this, please add this info to http://bugzilla.gnome.org/show_bug.cgi?id=368178", - file, file_uri, directory, dir_uri, nautilus_view_get_model (view), model_uri, nautilus_view_get_loading (view)); + file, file_uri, directory, dir_uri, nautilus_files_view_get_model (view), model_uri, nautilus_files_view_get_loading (view)); g_free (file_uri); g_free (dir_uri); g_free (model_uri); @@ -404,18 +404,18 @@ nautilus_canvas_view_remove_file (NautilusView *view, NautilusFile *file, Nautil } static void -nautilus_canvas_view_add_file (NautilusView *view, NautilusFile *file, NautilusDirectory *directory) +nautilus_canvas_view_add_file (NautilusFilesView *view, NautilusFile *file, NautilusDirectory *directory) { NautilusCanvasView *canvas_view; NautilusCanvasContainer *canvas_container; - g_assert (directory == nautilus_view_get_model (view)); + g_assert (directory == nautilus_files_view_get_model (view)); canvas_view = NAUTILUS_CANVAS_VIEW (view); canvas_container = get_canvas_container (canvas_view); /* Reset scroll region for the first canvas added when loading a directory. */ - if (nautilus_view_get_loading (view) && nautilus_canvas_container_is_empty (canvas_container)) { + if (nautilus_files_view_get_loading (view) && nautilus_canvas_container_is_empty (canvas_container)) { nautilus_canvas_container_reset_scroll_region (canvas_container); } @@ -426,11 +426,11 @@ nautilus_canvas_view_add_file (NautilusView *view, NautilusFile *file, NautilusD } static void -nautilus_canvas_view_file_changed (NautilusView *view, NautilusFile *file, NautilusDirectory *directory) +nautilus_canvas_view_file_changed (NautilusFilesView *view, NautilusFile *file, NautilusDirectory *directory) { NautilusCanvasView *canvas_view; - g_assert (directory == nautilus_view_get_model (view)); + g_assert (directory == nautilus_files_view_get_model (view)); g_return_if_fail (view != NULL); canvas_view = NAUTILUS_CANVAS_VIEW (view); @@ -642,7 +642,7 @@ set_sort_reversed (NautilusCanvasView *canvas_view, if (set_metadata) { /* 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); + nautilus_canvas_view_set_directory_sort_reversed (canvas_view, nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (canvas_view)), new_value); } return TRUE; @@ -702,7 +702,7 @@ get_default_zoom_level (NautilusCanvasView *canvas_view) } static void -nautilus_canvas_view_begin_loading (NautilusView *view) +nautilus_canvas_view_begin_loading (NautilusFilesView *view) { NautilusCanvasView *canvas_view; GtkWidget *canvas_container; @@ -712,7 +712,7 @@ nautilus_canvas_view_begin_loading (NautilusView *view) g_return_if_fail (NAUTILUS_IS_CANVAS_VIEW (view)); canvas_view = NAUTILUS_CANVAS_VIEW (view); - file = nautilus_view_get_directory_as_file (view); + file = nautilus_files_view_get_directory_as_file (view); uri = nautilus_file_get_uri (file); canvas_container = GTK_WIDGET (get_canvas_container (canvas_view)); @@ -745,8 +745,8 @@ nautilus_canvas_view_begin_loading (NautilusView *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); + nautilus_files_view_update_context_menus(view); + nautilus_files_view_update_toolbar_menus(view); } static void @@ -766,7 +766,7 @@ canvas_view_notify_clipboard_info (NautilusClipboardMonitor *monitor, } static void -nautilus_canvas_view_end_loading (NautilusView *view, +nautilus_canvas_view_end_loading (NautilusFilesView *view, gboolean all_files_seen) { NautilusCanvasView *canvas_view; @@ -786,7 +786,7 @@ nautilus_canvas_view_end_loading (NautilusView *view, } static NautilusCanvasZoomLevel -nautilus_canvas_view_get_zoom_level (NautilusView *view) +nautilus_canvas_view_get_zoom_level (NautilusFilesView *view) { g_return_val_if_fail (NAUTILUS_IS_CANVAS_VIEW (view), NAUTILUS_CANVAS_ZOOM_LEVEL_STANDARD); @@ -794,7 +794,7 @@ nautilus_canvas_view_get_zoom_level (NautilusView *view) } static void -nautilus_canvas_view_zoom_to_level (NautilusView *view, +nautilus_canvas_view_zoom_to_level (NautilusFilesView *view, gint new_level) { NautilusCanvasView *canvas_view; @@ -810,19 +810,19 @@ nautilus_canvas_view_zoom_to_level (NautilusView *view, return; nautilus_canvas_container_set_zoom_level (canvas_container, new_level); - g_action_group_change_action_state (nautilus_view_get_action_group (view), + g_action_group_change_action_state (nautilus_files_view_get_action_group (view), "zoom-to-level", g_variant_new_int32 (new_level)); - nautilus_view_update_toolbar_menus (view); + nautilus_files_view_update_toolbar_menus (view); } static void -nautilus_canvas_view_bump_zoom_level (NautilusView *view, int zoom_increment) +nautilus_canvas_view_bump_zoom_level (NautilusFilesView *view, int zoom_increment) { NautilusCanvasZoomLevel new_level; g_return_if_fail (NAUTILUS_IS_CANVAS_VIEW (view)); - if (!nautilus_view_supports_zooming (view)) { + if (!nautilus_files_view_supports_zooming (view)) { return; } @@ -835,7 +835,7 @@ nautilus_canvas_view_bump_zoom_level (NautilusView *view, int zoom_increment) } static void -nautilus_canvas_view_restore_default_zoom_level (NautilusView *view) +nautilus_canvas_view_restore_default_zoom_level (NautilusFilesView *view) { NautilusCanvasView *canvas_view; @@ -847,7 +847,7 @@ nautilus_canvas_view_restore_default_zoom_level (NautilusView *view) } static gboolean -nautilus_canvas_view_can_zoom_in (NautilusView *view) +nautilus_canvas_view_can_zoom_in (NautilusFilesView *view) { g_return_val_if_fail (NAUTILUS_IS_CANVAS_VIEW (view), FALSE); @@ -856,7 +856,7 @@ nautilus_canvas_view_can_zoom_in (NautilusView *view) } static gboolean -nautilus_canvas_view_can_zoom_out (NautilusView *view) +nautilus_canvas_view_can_zoom_out (NautilusFilesView *view) { g_return_val_if_fail (NAUTILUS_IS_CANVAS_VIEW (view), FALSE); @@ -865,7 +865,7 @@ nautilus_canvas_view_can_zoom_out (NautilusView *view) } static gboolean -nautilus_canvas_view_is_empty (NautilusView *view) +nautilus_canvas_view_is_empty (NautilusFilesView *view) { g_assert (NAUTILUS_IS_CANVAS_VIEW (view)); @@ -874,7 +874,7 @@ nautilus_canvas_view_is_empty (NautilusView *view) } static GList * -nautilus_canvas_view_get_selection (NautilusView *view) +nautilus_canvas_view_get_selection (NautilusFilesView *view) { GList *list; @@ -898,7 +898,7 @@ action_reversed_order (GSimpleAction *action, 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)); + nautilus_canvas_view_reveal_selection (NAUTILUS_FILES_VIEW (user_data)); } g_simple_action_set_state (action, state); @@ -914,7 +914,7 @@ action_keep_aligned (GSimpleAction *action, gboolean keep_aligned; canvas_view = NAUTILUS_CANVAS_VIEW (user_data); - file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (canvas_view)); + file = nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (canvas_view)); keep_aligned = g_variant_get_boolean (state); nautilus_canvas_view_set_directory_keep_aligned (canvas_view, @@ -949,7 +949,7 @@ action_sort_order_changed (GSimpleAction *action, 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)); + nautilus_canvas_view_reveal_selection (NAUTILUS_FILES_VIEW (user_data)); } g_simple_action_set_state (action, value); @@ -960,12 +960,12 @@ action_zoom_to_level (GSimpleAction *action, GVariant *state, gpointer user_data) { - NautilusView *view; + NautilusFilesView *view; NautilusCanvasZoomLevel zoom_level; - g_assert (NAUTILUS_IS_VIEW (user_data)); + g_assert (NAUTILUS_IS_FILES_VIEW (user_data)); - view = NAUTILUS_VIEW (user_data); + view = NAUTILUS_FILES_VIEW (user_data); zoom_level = g_variant_get_int32 (state); nautilus_canvas_view_zoom_to_level (view, zoom_level); @@ -979,7 +979,7 @@ static void switch_to_manual_layout (NautilusCanvasView *canvas_view) { if (!nautilus_canvas_view_using_auto_layout (canvas_view) || - !nautilus_view_is_editable (NAUTILUS_VIEW (canvas_view))) { + !nautilus_files_view_is_editable (NAUTILUS_FILES_VIEW (canvas_view))) { return; } @@ -998,7 +998,7 @@ layout_changed_callback (NautilusCanvasContainer *container, g_assert (NAUTILUS_IS_CANVAS_VIEW (canvas_view)); g_assert (container == get_canvas_container (canvas_view)); - file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (canvas_view)); + file = nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (canvas_view)); if (file != NULL) { nautilus_canvas_view_set_directory_auto_layout @@ -1009,9 +1009,9 @@ layout_changed_callback (NautilusCanvasContainer *container, } static gboolean -nautilus_canvas_view_can_rename_file (NautilusView *view, NautilusFile *file) +nautilus_canvas_view_can_rename_file (NautilusFilesView *view, NautilusFile *file) { - return NAUTILUS_VIEW_CLASS(nautilus_canvas_view_parent_class)->can_rename_file (view, file); + return NAUTILUS_FILES_VIEW_CLASS(nautilus_canvas_view_parent_class)->can_rename_file (view, file); } const GActionEntry canvas_view_entries[] = { @@ -1031,7 +1031,7 @@ update_sort_action_state_hint (NautilusCanvasView *canvas_view) GVariant *state_hint; gint idx; - file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (canvas_view)); + file = nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (canvas_view)); g_variant_builder_init (&builder, G_VARIANT_TYPE ("as")); for (idx = 0; idx < G_N_ELEMENTS (sort_criteria); idx++) { @@ -1042,7 +1042,7 @@ update_sort_action_state_hint (NautilusCanvasView *canvas_view) state_hint = g_variant_builder_end (&builder); - action_group = nautilus_view_get_action_group (NAUTILUS_VIEW (canvas_view)); + action_group = nautilus_files_view_get_action_group (NAUTILUS_FILES_VIEW (canvas_view)); action = g_action_map_lookup_action (G_ACTION_MAP (action_group), "sort"); g_simple_action_set_state_hint (G_SIMPLE_ACTION (action), state_hint); @@ -1050,11 +1050,11 @@ update_sort_action_state_hint (NautilusCanvasView *canvas_view) } static gboolean -showing_recent_directory (NautilusView *view) +showing_recent_directory (NautilusFilesView *view) { NautilusFile *file; - file = nautilus_view_get_directory_as_file (view); + file = nautilus_files_view_get_directory_as_file (view); if (file != NULL) { return nautilus_file_is_in_recent (file); } @@ -1062,11 +1062,11 @@ showing_recent_directory (NautilusView *view) } static gboolean -showing_search_directory (NautilusView *view) +showing_search_directory (NautilusFilesView *view) { NautilusFile *file; - file = nautilus_view_get_directory_as_file (view); + file = nautilus_files_view_get_directory_as_file (view); if (file != NULL) { return nautilus_file_is_in_search (file); } @@ -1074,7 +1074,7 @@ showing_search_directory (NautilusView *view) } static void -nautilus_canvas_view_update_actions_state (NautilusView *view) +nautilus_canvas_view_update_actions_state (NautilusFilesView *view) { GActionGroup *view_action_group; GAction *action; @@ -1083,9 +1083,9 @@ nautilus_canvas_view_update_actions_state (NautilusView *view) canvas_view = NAUTILUS_CANVAS_VIEW (view); - NAUTILUS_VIEW_CLASS (nautilus_canvas_view_parent_class)->update_actions_state (view); + NAUTILUS_FILES_VIEW_CLASS (nautilus_canvas_view_parent_class)->update_actions_state (view); - view_action_group = nautilus_view_get_action_group (view); + view_action_group = nautilus_files_view_get_action_group (view); if (nautilus_canvas_view_supports_auto_layout (canvas_view)) { GVariant *sort_state; GVariant *reversed_state; @@ -1134,7 +1134,7 @@ nautilus_canvas_view_update_actions_state (NautilusView *view) } static void -nautilus_canvas_view_select_all (NautilusView *view) +nautilus_canvas_view_select_all (NautilusFilesView *view) { NautilusCanvasContainer *canvas_container; @@ -1145,7 +1145,7 @@ nautilus_canvas_view_select_all (NautilusView *view) } static void -nautilus_canvas_view_select_first (NautilusView *view) +nautilus_canvas_view_select_first (NautilusFilesView *view) { NautilusCanvasContainer *canvas_container; @@ -1156,13 +1156,13 @@ nautilus_canvas_view_select_first (NautilusView *view) } static void -nautilus_canvas_view_reveal_selection (NautilusView *view) +nautilus_canvas_view_reveal_selection (NautilusFilesView *view) { GList *selection; g_return_if_fail (NAUTILUS_IS_CANVAS_VIEW (view)); - selection = nautilus_view_get_selection (view); + selection = nautilus_files_view_get_selection (view); /* Make sure at least one of the selected items is scrolled into view */ if (selection != NULL) { @@ -1175,7 +1175,7 @@ nautilus_canvas_view_reveal_selection (NautilusView *view) } static GdkRectangle* -nautilus_canvas_view_compute_rename_popover_relative_to (NautilusView *view) +nautilus_canvas_view_compute_rename_popover_relative_to (NautilusFilesView *view) { GArray *bounding_boxes; GdkRectangle *bounding_box; @@ -1187,7 +1187,7 @@ nautilus_canvas_view_compute_rename_popover_relative_to (NautilusView *view) bounding_boxes = nautilus_canvas_container_get_selected_icons_bounding_box (canvas_container); /* We only allow renaming one item at once */ bounding_box = &g_array_index (bounding_boxes, GdkRectangle, 0); - parent_container = nautilus_view_get_content_widget (view); + parent_container = nautilus_files_view_get_content_widget (view); vadjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (parent_container)); hadjustment = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (parent_container)); @@ -1200,7 +1200,7 @@ nautilus_canvas_view_compute_rename_popover_relative_to (NautilusView *view) } static GArray * -nautilus_canvas_view_get_selected_icon_locations (NautilusView *view) +nautilus_canvas_view_get_selected_icon_locations (NautilusFilesView *view) { g_return_val_if_fail (NAUTILUS_IS_CANVAS_VIEW (view), NULL); @@ -1210,7 +1210,7 @@ nautilus_canvas_view_get_selected_icon_locations (NautilusView *view) static void -nautilus_canvas_view_set_selection (NautilusView *view, GList *selection) +nautilus_canvas_view_set_selection (NautilusFilesView *view, GList *selection) { g_return_if_fail (NAUTILUS_IS_CANVAS_VIEW (view)); @@ -1219,7 +1219,7 @@ nautilus_canvas_view_set_selection (NautilusView *view, GList *selection) } static void -nautilus_canvas_view_invert_selection (NautilusView *view) +nautilus_canvas_view_invert_selection (NautilusFilesView *view) { g_return_if_fail (NAUTILUS_IS_CANVAS_VIEW (view)); @@ -1228,7 +1228,7 @@ nautilus_canvas_view_invert_selection (NautilusView *view) } static gboolean -nautilus_canvas_view_using_manual_layout (NautilusView *view) +nautilus_canvas_view_using_manual_layout (NautilusFilesView *view) { g_return_val_if_fail (NAUTILUS_IS_CANVAS_VIEW (view), FALSE); @@ -1236,7 +1236,7 @@ nautilus_canvas_view_using_manual_layout (NautilusView *view) } static void -nautilus_canvas_view_widget_to_file_operation_position (NautilusView *view, +nautilus_canvas_view_widget_to_file_operation_position (NautilusFilesView *view, GdkPoint *position) { g_assert (NAUTILUS_IS_CANVAS_VIEW (view)); @@ -1253,7 +1253,7 @@ canvas_container_activate_callback (NautilusCanvasContainer *container, g_assert (NAUTILUS_IS_CANVAS_VIEW (canvas_view)); g_assert (container == get_canvas_container (canvas_view)); - nautilus_view_activate_files (NAUTILUS_VIEW (canvas_view), + nautilus_files_view_activate_files (NAUTILUS_FILES_VIEW (canvas_view), file_list, 0, TRUE); } @@ -1267,7 +1267,7 @@ canvas_container_activate_previewer_callback (NautilusCanvasContainer *container g_assert (NAUTILUS_IS_CANVAS_VIEW (canvas_view)); g_assert (container == get_canvas_container (canvas_view)); - nautilus_view_preview_files (NAUTILUS_VIEW (canvas_view), + nautilus_files_view_preview_files (NAUTILUS_FILES_VIEW (canvas_view), file_list, locations); } @@ -1332,7 +1332,7 @@ canvas_container_activate_alternate_callback (NautilusCanvasContainer *container DEBUG ("Activate alternate, open in tab %d, close behind %d, new window %d\n", open_in_tab, close_behind, open_in_window); - nautilus_view_activate_files (NAUTILUS_VIEW (canvas_view), + nautilus_files_view_activate_files (NAUTILUS_FILES_VIEW (canvas_view), file_list, flags, TRUE); @@ -1345,7 +1345,7 @@ band_select_started_callback (NautilusCanvasContainer *container, g_assert (NAUTILUS_IS_CANVAS_VIEW (canvas_view)); g_assert (container == get_canvas_container (canvas_view)); - nautilus_view_start_batching_selection_changes (NAUTILUS_VIEW (canvas_view)); + nautilus_files_view_start_batching_selection_changes (NAUTILUS_FILES_VIEW (canvas_view)); } static void @@ -1355,7 +1355,7 @@ band_select_ended_callback (NautilusCanvasContainer *container, g_assert (NAUTILUS_IS_CANVAS_VIEW (canvas_view)); g_assert (container == get_canvas_container (canvas_view)); - nautilus_view_stop_batching_selection_changes (NAUTILUS_VIEW (canvas_view)); + nautilus_files_view_stop_batching_selection_changes (NAUTILUS_FILES_VIEW (canvas_view)); } int @@ -1366,12 +1366,12 @@ nautilus_canvas_view_compare_files (NautilusCanvasView *canvas_view, return nautilus_file_compare_for_sort (a, b, canvas_view->details->sort->sort_type, /* Use type-unsafe cast for performance */ - nautilus_view_should_sort_directories_first ((NautilusView *)canvas_view), + nautilus_files_view_should_sort_directories_first ((NautilusFilesView *)canvas_view), canvas_view->details->sort_reversed); } static int -compare_files (NautilusView *canvas_view, +compare_files (NautilusFilesView *canvas_view, NautilusFile *a, NautilusFile *b) { @@ -1385,7 +1385,7 @@ selection_changed_callback (NautilusCanvasContainer *container, g_assert (NAUTILUS_IS_CANVAS_VIEW (canvas_view)); g_assert (container == get_canvas_container (canvas_view)); - nautilus_view_notify_selection_changed (NAUTILUS_VIEW (canvas_view)); + nautilus_files_view_notify_selection_changed (NAUTILUS_FILES_VIEW (canvas_view)); } static void @@ -1396,7 +1396,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_files_view_pop_up_selection_context_menu (NAUTILUS_FILES_VIEW (canvas_view), event); } static void @@ -1407,7 +1407,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); + nautilus_files_view_pop_up_background_context_menu (NAUTILUS_FILES_VIEW (canvas_view), event); } static void @@ -1478,7 +1478,7 @@ get_icon_drop_target_uri_callback (NautilusCanvasContainer *container, /* Preferences changed callbacks */ static void -nautilus_canvas_view_click_policy_changed (NautilusView *directory_view) +nautilus_canvas_view_click_policy_changed (NautilusFilesView *directory_view) { g_assert (NAUTILUS_IS_CANVAS_VIEW (directory_view)); @@ -1517,7 +1517,7 @@ default_sort_order_changed_callback (gpointer callback_data) canvas_view = NAUTILUS_CANVAS_VIEW (callback_data); - file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (canvas_view)); + file = nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (canvas_view)); sort_name = nautilus_canvas_view_get_directory_sort_by (canvas_view, file); set_sort_criterion (canvas_view, get_sort_criterion_by_metadata_text (sort_name), FALSE); g_free (sort_name); @@ -1539,7 +1539,7 @@ default_sort_in_reverse_order_changed_callback (gpointer callback_data) canvas_view = NAUTILUS_CANVAS_VIEW (callback_data); - file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (canvas_view)); + file = nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (canvas_view)); set_sort_reversed (canvas_view, nautilus_canvas_view_get_directory_sort_reversed (canvas_view, file), FALSE); canvas_container = get_canvas_container (canvas_view); g_return_if_fail (NAUTILUS_IS_CANVAS_CONTAINER (canvas_container)); @@ -1548,7 +1548,7 @@ default_sort_in_reverse_order_changed_callback (gpointer callback_data) } static void -nautilus_canvas_view_sort_directories_first_changed (NautilusView *directory_view) +nautilus_canvas_view_sort_directories_first_changed (NautilusFilesView *directory_view) { NautilusCanvasView *canvas_view; @@ -1564,16 +1564,16 @@ static gboolean canvas_view_can_accept_item (NautilusCanvasContainer *container, NautilusFile *target_item, const char *item_uri, - NautilusView *view) + NautilusFilesView *view) { return nautilus_drag_can_accept_item (target_item, item_uri); } static char * canvas_view_get_container_uri (NautilusCanvasContainer *container, - NautilusView *view) + NautilusFilesView *view) { - return nautilus_view_get_uri (view); + return nautilus_files_view_get_uri (view); } static void @@ -1583,12 +1583,12 @@ canvas_view_move_copy_items (NautilusCanvasContainer *container, const char *target_dir, int copy_action, int x, int y, - NautilusView *view) + NautilusFilesView *view) { nautilus_clipboard_clear_if_colliding_uris (GTK_WIDGET (view), item_uris, - nautilus_view_get_copied_files_atom (view)); - nautilus_view_move_copy_items (view, item_uris, relative_item_points, target_dir, + nautilus_files_view_get_copied_files_atom (view)); + nautilus_files_view_move_copy_items (view, item_uris, relative_item_points, target_dir, copy_action, x, y); } @@ -1617,7 +1617,7 @@ get_stored_layout_timestamp (NautilusCanvasContainer *container, NautilusDirectory *directory; if (icon_data == NULL) { - directory = nautilus_view_get_model (NAUTILUS_VIEW (view)); + directory = nautilus_files_view_get_model (NAUTILUS_FILES_VIEW (view)); if (directory == NULL) { return FALSE; } @@ -1644,7 +1644,7 @@ store_layout_timestamp (NautilusCanvasContainer *container, NautilusDirectory *directory; if (icon_data == NULL) { - directory = nautilus_view_get_model (NAUTILUS_VIEW (view)); + directory = nautilus_files_view_get_model (NAUTILUS_FILES_VIEW (view)); if (directory == NULL) { return FALSE; } @@ -1669,7 +1669,7 @@ create_canvas_container (NautilusCanvasView *canvas_view) NautilusCanvasContainer *canvas_container; GtkWidget *content_widget; - content_widget = nautilus_view_get_content_widget (NAUTILUS_VIEW (canvas_view)); + content_widget = nautilus_files_view_get_content_widget (NAUTILUS_FILES_VIEW (canvas_view)); canvas_container = nautilus_canvas_view_container_new (canvas_view); canvas_view->details->canvas_container = GTK_WIDGET (canvas_container); g_object_add_weak_pointer (G_OBJECT (canvas_container), @@ -1713,10 +1713,10 @@ create_canvas_container (NautilusCanvasView *canvas_view) g_signal_connect_object (canvas_container, "layout-changed", G_CALLBACK (layout_changed_callback), canvas_view, 0); g_signal_connect_object (canvas_container, "icon-stretch-started", - G_CALLBACK (nautilus_view_update_context_menus), canvas_view, + G_CALLBACK (nautilus_files_view_update_context_menus), canvas_view, G_CONNECT_SWAPPED); g_signal_connect_object (canvas_container, "icon-stretch-ended", - G_CALLBACK (nautilus_view_update_context_menus), canvas_view, + G_CALLBACK (nautilus_files_view_update_context_menus), canvas_view, G_CONNECT_SWAPPED); g_signal_connect_object (canvas_container, "get-stored-layout-timestamp", @@ -1742,7 +1742,7 @@ canvas_view_handle_netscape_url (NautilusCanvasContainer *container, const char const char *target_uri, GdkDragAction action, int x, int y, NautilusCanvasView *view) { - nautilus_view_handle_netscape_url_drop (NAUTILUS_VIEW (view), + nautilus_files_view_handle_netscape_url_drop (NAUTILUS_FILES_VIEW (view), encoded_url, target_uri, action, x, y); } @@ -1751,7 +1751,7 @@ canvas_view_handle_uri_list (NautilusCanvasContainer *container, const char *ite const char *target_uri, GdkDragAction action, int x, int y, NautilusCanvasView *view) { - nautilus_view_handle_uri_list_drop (NAUTILUS_VIEW (view), + nautilus_files_view_handle_uri_list_drop (NAUTILUS_FILES_VIEW (view), item_uris, target_uri, action, x, y); } @@ -1760,7 +1760,7 @@ canvas_view_handle_text (NautilusCanvasContainer *container, const char *text, const char *target_uri, GdkDragAction action, int x, int y, NautilusCanvasView *view) { - nautilus_view_handle_text_drop (NAUTILUS_VIEW (view), + nautilus_files_view_handle_text_drop (NAUTILUS_FILES_VIEW (view), text, target_uri, action, x, y); } @@ -1769,7 +1769,7 @@ canvas_view_handle_raw (NautilusCanvasContainer *container, const char *raw_data int length, const char *target_uri, const char *direct_save_uri, GdkDragAction action, int x, int y, NautilusCanvasView *view) { - nautilus_view_handle_raw_drop (NAUTILUS_VIEW (view), + nautilus_files_view_handle_raw_drop (NAUTILUS_FILES_VIEW (view), raw_data, length, target_uri, direct_save_uri, action, x, y); } @@ -1778,11 +1778,11 @@ canvas_view_handle_hover (NautilusCanvasContainer *container, const char *target_uri, NautilusCanvasView *view) { - nautilus_view_handle_hover (NAUTILUS_VIEW (view), target_uri); + nautilus_files_view_handle_hover (NAUTILUS_FILES_VIEW (view), target_uri); } static char * -canvas_view_get_first_visible_file (NautilusView *view) +canvas_view_get_first_visible_file (NautilusFilesView *view) { NautilusFile *file; NautilusCanvasView *canvas_view; @@ -1799,7 +1799,7 @@ canvas_view_get_first_visible_file (NautilusView *view) } static void -canvas_view_scroll_to_file (NautilusView *view, +canvas_view_scroll_to_file (NautilusFilesView *view, const char *uri) { NautilusFile *file; @@ -1820,7 +1820,7 @@ canvas_view_scroll_to_file (NautilusView *view, } static const char * -nautilus_canvas_view_get_id (NautilusView *view) +nautilus_canvas_view_get_id (NautilusFilesView *view) { return NAUTILUS_CANVAS_VIEW_ID; } @@ -1883,7 +1883,7 @@ nautilus_canvas_view_finalize (GObject *object) } static GIcon* -nautilus_canvas_view_get_icon (NautilusView *view) +nautilus_canvas_view_get_icon (NautilusFilesView *view) { g_return_val_if_fail (NAUTILUS_IS_CANVAS_VIEW (view), NULL); @@ -1893,10 +1893,10 @@ nautilus_canvas_view_get_icon (NautilusView *view) static void nautilus_canvas_view_class_init (NautilusCanvasViewClass *klass) { - NautilusViewClass *nautilus_view_class; + NautilusFilesViewClass *nautilus_files_view_class; GObjectClass *oclass; - nautilus_view_class = NAUTILUS_VIEW_CLASS (klass); + nautilus_files_view_class = NAUTILUS_FILES_VIEW_CLASS (klass); oclass = G_OBJECT_CLASS (klass); oclass->set_property = nautilus_canvas_view_set_property; @@ -1904,37 +1904,37 @@ nautilus_canvas_view_class_init (NautilusCanvasViewClass *klass) GTK_WIDGET_CLASS (klass)->destroy = nautilus_canvas_view_destroy; - 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->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; - nautilus_view_class->clear = nautilus_canvas_view_clear; - nautilus_view_class->end_loading = nautilus_canvas_view_end_loading; - nautilus_view_class->file_changed = nautilus_canvas_view_file_changed; - nautilus_view_class->get_selected_icon_locations = nautilus_canvas_view_get_selected_icon_locations; - nautilus_view_class->compute_rename_popover_relative_to = nautilus_canvas_view_compute_rename_popover_relative_to; - nautilus_view_class->get_selection = nautilus_canvas_view_get_selection; - nautilus_view_class->get_selection_for_file_transfer = nautilus_canvas_view_get_selection; - nautilus_view_class->is_empty = nautilus_canvas_view_is_empty; - nautilus_view_class->remove_file = nautilus_canvas_view_remove_file; - nautilus_view_class->restore_default_zoom_level = nautilus_canvas_view_restore_default_zoom_level; - nautilus_view_class->reveal_selection = nautilus_canvas_view_reveal_selection; - nautilus_view_class->select_all = nautilus_canvas_view_select_all; - nautilus_view_class->select_first = nautilus_canvas_view_select_first; - nautilus_view_class->set_selection = nautilus_canvas_view_set_selection; - nautilus_view_class->invert_selection = nautilus_canvas_view_invert_selection; - nautilus_view_class->compare_files = compare_files; - nautilus_view_class->click_policy_changed = nautilus_canvas_view_click_policy_changed; - 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->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; - nautilus_view_class->get_first_visible_file = canvas_view_get_first_visible_file; - nautilus_view_class->scroll_to_file = canvas_view_scroll_to_file; - nautilus_view_class->get_icon = nautilus_canvas_view_get_icon; + nautilus_files_view_class->add_file = nautilus_canvas_view_add_file; + nautilus_files_view_class->begin_loading = nautilus_canvas_view_begin_loading; + nautilus_files_view_class->bump_zoom_level = nautilus_canvas_view_bump_zoom_level; + nautilus_files_view_class->can_rename_file = nautilus_canvas_view_can_rename_file; + nautilus_files_view_class->can_zoom_in = nautilus_canvas_view_can_zoom_in; + nautilus_files_view_class->can_zoom_out = nautilus_canvas_view_can_zoom_out; + nautilus_files_view_class->clear = nautilus_canvas_view_clear; + nautilus_files_view_class->end_loading = nautilus_canvas_view_end_loading; + nautilus_files_view_class->file_changed = nautilus_canvas_view_file_changed; + nautilus_files_view_class->get_selected_icon_locations = nautilus_canvas_view_get_selected_icon_locations; + nautilus_files_view_class->compute_rename_popover_relative_to = nautilus_canvas_view_compute_rename_popover_relative_to; + nautilus_files_view_class->get_selection = nautilus_canvas_view_get_selection; + nautilus_files_view_class->get_selection_for_file_transfer = nautilus_canvas_view_get_selection; + nautilus_files_view_class->is_empty = nautilus_canvas_view_is_empty; + nautilus_files_view_class->remove_file = nautilus_canvas_view_remove_file; + nautilus_files_view_class->restore_default_zoom_level = nautilus_canvas_view_restore_default_zoom_level; + nautilus_files_view_class->reveal_selection = nautilus_canvas_view_reveal_selection; + nautilus_files_view_class->select_all = nautilus_canvas_view_select_all; + nautilus_files_view_class->select_first = nautilus_canvas_view_select_first; + nautilus_files_view_class->set_selection = nautilus_canvas_view_set_selection; + nautilus_files_view_class->invert_selection = nautilus_canvas_view_invert_selection; + nautilus_files_view_class->compare_files = compare_files; + nautilus_files_view_class->click_policy_changed = nautilus_canvas_view_click_policy_changed; + nautilus_files_view_class->update_actions_state = nautilus_canvas_view_update_actions_state; + nautilus_files_view_class->sort_directories_first_changed = nautilus_canvas_view_sort_directories_first_changed; + nautilus_files_view_class->using_manual_layout = nautilus_canvas_view_using_manual_layout; + nautilus_files_view_class->widget_to_file_operation_position = nautilus_canvas_view_widget_to_file_operation_position; + nautilus_files_view_class->get_view_id = nautilus_canvas_view_get_id; + nautilus_files_view_class->get_first_visible_file = canvas_view_get_first_visible_file; + nautilus_files_view_class->scroll_to_file = canvas_view_scroll_to_file; + nautilus_files_view_class->get_icon = nautilus_canvas_view_get_icon; properties[PROP_SUPPORTS_AUTO_LAYOUT] = g_param_spec_boolean ("supports-auto-layout", @@ -2014,17 +2014,17 @@ nautilus_canvas_view_init (NautilusCanvasView *canvas_view) "clipboard-info", G_CALLBACK (canvas_view_notify_clipboard_info), canvas_view); - view_action_group = nautilus_view_get_action_group (NAUTILUS_VIEW (canvas_view)); + view_action_group = nautilus_files_view_get_action_group (NAUTILUS_FILES_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); /* Keep the action synced with the actual value, so the toolbar can poll it */ - g_action_group_change_action_state (nautilus_view_get_action_group (NAUTILUS_VIEW (canvas_view)), + g_action_group_change_action_state (nautilus_files_view_get_action_group (NAUTILUS_FILES_VIEW (canvas_view)), "zoom-to-level", g_variant_new_int32 (get_default_zoom_level (canvas_view))); } -NautilusView * +NautilusFilesView * nautilus_canvas_view_new (NautilusWindowSlot *slot) { return g_object_new (NAUTILUS_TYPE_CANVAS_VIEW, diff --git a/src/nautilus-canvas-view.h b/src/nautilus-canvas-view.h index e2b77edf9..994b51f31 100644 --- a/src/nautilus-canvas-view.h +++ b/src/nautilus-canvas-view.h @@ -25,7 +25,7 @@ #ifndef NAUTILUS_CANVAS_VIEW_H #define NAUTILUS_CANVAS_VIEW_H -#include "nautilus-view.h" +#include "nautilus-files-view.h" #include "libnautilus-private/nautilus-canvas-container.h" typedef struct NautilusCanvasView NautilusCanvasView; @@ -46,12 +46,12 @@ typedef struct NautilusCanvasViewClass NautilusCanvasViewClass; typedef struct NautilusCanvasViewDetails NautilusCanvasViewDetails; struct NautilusCanvasView { - NautilusView parent; + NautilusFilesView parent; NautilusCanvasViewDetails *details; }; struct NautilusCanvasViewClass { - NautilusViewClass parent_class; + NautilusFilesViewClass parent_class; }; /* GObject support */ @@ -63,7 +63,7 @@ void nautilus_canvas_view_filter_by_screen (NautilusCanvasView *canvas_view, gboolean filter); void nautilus_canvas_view_clean_up_by_name (NautilusCanvasView *canvas_view); -NautilusView * nautilus_canvas_view_new (NautilusWindowSlot *slot); +NautilusFilesView * nautilus_canvas_view_new (NautilusWindowSlot *slot); NautilusCanvasContainer * nautilus_canvas_view_get_canvas_container (NautilusCanvasView *view); diff --git a/src/nautilus-desktop-canvas-view.c b/src/nautilus-desktop-canvas-view.c index 6890743ce..49910b027 100644 --- a/src/nautilus-desktop-canvas-view.c +++ b/src/nautilus-desktop-canvas-view.c @@ -29,7 +29,7 @@ #include "nautilus-desktop-canvas-view.h" #include "nautilus-canvas-view-container.h" -#include "nautilus-view.h" +#include "nautilus-files-view.h" #include <X11/Xatom.h> #include <gtk/gtk.h> @@ -74,7 +74,7 @@ struct NautilusDesktopCanvasViewDetails }; static void default_zoom_level_changed (gpointer user_data); -static void real_update_context_menus (NautilusView *view); +static void real_update_context_menus (NautilusFilesView *view); static void nautilus_desktop_canvas_view_update_canvas_container_fonts (NautilusDesktopCanvasView *view); static void font_changed_callback (gpointer callback_data); @@ -227,7 +227,7 @@ desktop_canvas_view_property_filter (GdkXEvent *gdk_xevent, } static const char * -real_get_id (NautilusView *view) +real_get_id (NautilusFilesView *view) { return NAUTILUS_DESKTOP_CANVAS_VIEW_ID; } @@ -252,14 +252,14 @@ nautilus_desktop_canvas_view_dispose (GObject *object) font_changed_callback, canvas_view); g_signal_handlers_disconnect_by_func (gnome_lockdown_preferences, - nautilus_view_update_context_menus, + nautilus_files_view_update_context_menus, canvas_view); G_OBJECT_CLASS (nautilus_desktop_canvas_view_parent_class)->dispose (object); } static void -nautilus_desktop_canvas_view_end_loading (NautilusView *view, +nautilus_desktop_canvas_view_end_loading (NautilusFilesView *view, gboolean all_files_seen) { gboolean needs_reorganization; @@ -269,12 +269,12 @@ nautilus_desktop_canvas_view_end_loading (NautilusView *view, gchar *current_icon_size_string; NautilusFile *file; - NAUTILUS_VIEW_CLASS (nautilus_desktop_canvas_view_parent_class)->end_loading (view, all_files_seen); + NAUTILUS_FILES_VIEW_CLASS (nautilus_desktop_canvas_view_parent_class)->end_loading (view, all_files_seen); if (!all_files_seen) return; - file = nautilus_view_get_directory_as_file (view); + file = nautilus_files_view_get_directory_as_file (view); g_return_if_fail (file != NULL); stored_size_icon = nautilus_file_get_metadata (file, NAUTILUS_METADATA_KEY_DESKTOP_ICON_SIZE, NULL); @@ -297,9 +297,9 @@ nautilus_desktop_canvas_view_end_loading (NautilusView *view, static void nautilus_desktop_canvas_view_class_init (NautilusDesktopCanvasViewClass *class) { - NautilusViewClass *vclass; + NautilusFilesViewClass *vclass; - vclass = NAUTILUS_VIEW_CLASS (class); + vclass = NAUTILUS_FILES_VIEW_CLASS (class); G_OBJECT_CLASS (class)->dispose = nautilus_desktop_canvas_view_dispose; @@ -387,7 +387,7 @@ default_zoom_level_changed (gpointer user_data) gchar *new_icon_size_string; desktop_canvas_view = NAUTILUS_DESKTOP_CANVAS_VIEW (user_data); - file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (user_data)); + file = nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (user_data)); new_level = get_default_zoom_level (); new_icon_size = nautilus_canvas_container_get_icon_size_for_zoom_level (new_level); new_icon_size_string = g_strdup_printf ("%d", new_icon_size); @@ -421,7 +421,7 @@ do_desktop_rescan (gpointer data) desktop_canvas_view->details->pending_rescan = TRUE; nautilus_directory_force_reload - (nautilus_view_get_model (NAUTILUS_VIEW (desktop_canvas_view))); + (nautilus_files_view_get_model (NAUTILUS_FILES_VIEW (desktop_canvas_view))); return TRUE; } @@ -448,7 +448,7 @@ static void delayed_init (NautilusDesktopCanvasView *desktop_canvas_view) { /* Keep track of the load time. */ - g_signal_connect_object (nautilus_view_get_model (NAUTILUS_VIEW (desktop_canvas_view)), + g_signal_connect_object (nautilus_files_view_get_model (NAUTILUS_FILES_VIEW (desktop_canvas_view)), "done-loading", G_CALLBACK (done_loading), desktop_canvas_view, 0); @@ -550,7 +550,7 @@ action_change_background (GSimpleAction *action, { const gchar *control_center_cmd, *params; - g_assert (NAUTILUS_VIEW (user_data)); + g_assert (NAUTILUS_FILES_VIEW (user_data)); control_center_cmd = get_control_center_command (¶ms); if (control_center_cmd == NULL) { @@ -568,7 +568,7 @@ action_empty_trash (GSimpleAction *action, GVariant *state, gpointer user_data) { - g_assert (NAUTILUS_IS_VIEW (user_data)); + g_assert (NAUTILUS_IS_FILES_VIEW (user_data)); nautilus_file_operations_empty_trash (GTK_WIDGET (user_data)); } @@ -599,7 +599,7 @@ action_organize_desktop_by_name (GSimpleAction *action, } static gboolean -trash_link_is_selection (NautilusView *view) +trash_link_is_selection (NautilusFilesView *view) { GList *selection; NautilusDesktopLink *link; @@ -607,7 +607,7 @@ trash_link_is_selection (NautilusView *view) result = FALSE; - selection = nautilus_view_get_selection (view); + selection = nautilus_files_view_get_selection (view); if ((g_list_length (selection) == 1) && NAUTILUS_IS_DESKTOP_ICON_FILE (selection->data)) { @@ -636,7 +636,7 @@ const GActionEntry desktop_view_entries[] = { }; static void -real_update_context_menus (NautilusView *view) +real_update_context_menus (NautilusFilesView *view) { NautilusCanvasContainer *canvas_container; NautilusDesktopCanvasView *desktop_view; @@ -646,9 +646,9 @@ real_update_context_menus (NautilusView *view) g_assert (NAUTILUS_IS_DESKTOP_CANVAS_VIEW (view)); - NAUTILUS_VIEW_CLASS (nautilus_desktop_canvas_view_parent_class)->update_context_menus (view); + NAUTILUS_FILES_VIEW_CLASS (nautilus_desktop_canvas_view_parent_class)->update_context_menus (view); - view_action_group = nautilus_view_get_action_group (view); + view_action_group = nautilus_files_view_get_action_group (view); desktop_view = NAUTILUS_DESKTOP_CANVAS_VIEW (view); action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), "empty-trash"); @@ -664,7 +664,7 @@ real_update_context_menus (NautilusView *view) g_simple_action_set_enabled (G_SIMPLE_ACTION (action), TRUE); /* Stretch */ - selection_count = nautilus_view_get_selection_count (view); + selection_count = nautilus_files_view_get_selection_count (view); canvas_container = get_canvas_container (desktop_view); action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), "stretch"); @@ -723,10 +723,10 @@ nautilus_desktop_canvas_view_init (NautilusDesktopCanvasView *desktop_canvas_vie gtk_adjustment_set_value (hadj, 0); gtk_adjustment_set_value (vadj, 0); - nautilus_view_ignore_hidden_file_preferences - (NAUTILUS_VIEW (desktop_canvas_view)); + nautilus_files_view_ignore_hidden_file_preferences + (NAUTILUS_FILES_VIEW (desktop_canvas_view)); - nautilus_view_set_show_foreign (NAUTILUS_VIEW (desktop_canvas_view), + nautilus_files_view_set_show_foreign (NAUTILUS_FILES_VIEW (desktop_canvas_view), FALSE); g_signal_connect_object (canvas_container, "realize", @@ -752,18 +752,18 @@ 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_context_menus), + G_CALLBACK (nautilus_files_view_update_context_menus), desktop_canvas_view); - view_action_group = nautilus_view_get_action_group (NAUTILUS_VIEW (desktop_canvas_view)); + view_action_group = nautilus_files_view_get_action_group (NAUTILUS_FILES_VIEW (desktop_canvas_view)); g_action_map_add_action_entries (G_ACTION_MAP (view_action_group), desktop_view_entries, G_N_ELEMENTS (desktop_view_entries), - NAUTILUS_VIEW (desktop_canvas_view)); + NAUTILUS_FILES_VIEW (desktop_canvas_view)); } -NautilusView * +NautilusFilesView * nautilus_desktop_canvas_view_new (NautilusWindowSlot *slot) { return g_object_new (NAUTILUS_TYPE_DESKTOP_CANVAS_VIEW, diff --git a/src/nautilus-desktop-canvas-view.h b/src/nautilus-desktop-canvas-view.h index 8d0c4a470..0c9d0dd6d 100644 --- a/src/nautilus-desktop-canvas-view.h +++ b/src/nautilus-desktop-canvas-view.h @@ -50,6 +50,6 @@ typedef struct { /* GObject support */ GType nautilus_desktop_canvas_view_get_type (void); -NautilusView * nautilus_desktop_canvas_view_new (NautilusWindowSlot *slot); +NautilusFilesView * nautilus_desktop_canvas_view_new (NautilusWindowSlot *slot); #endif /* NAUTILUS_DESKTOP_CANVAS_VIEW_H */ diff --git a/src/nautilus-empty-view.c b/src/nautilus-empty-view.c index 5ece1c4bf..f87351d3c 100644 --- a/src/nautilus-empty-view.c +++ b/src/nautilus-empty-view.c @@ -25,7 +25,7 @@ #include "nautilus-empty-view.h" -#include "nautilus-view.h" +#include "nautilus-files-view.h" #include <string.h> #include <libnautilus-private/nautilus-file-utilities.h> @@ -35,15 +35,15 @@ struct NautilusEmptyViewDetails { int number_of_files; }; -static GList *nautilus_empty_view_get_selection (NautilusView *view); -static GList *nautilus_empty_view_get_selection_for_file_transfer (NautilusView *view); -static void nautilus_empty_view_scroll_to_file (NautilusView *view, +static GList *nautilus_empty_view_get_selection (NautilusFilesView *view); +static GList *nautilus_empty_view_get_selection_for_file_transfer (NautilusFilesView *view); +static void nautilus_empty_view_scroll_to_file (NautilusFilesView *view, const char *uri); -G_DEFINE_TYPE (NautilusEmptyView, nautilus_empty_view, NAUTILUS_TYPE_VIEW) +G_DEFINE_TYPE (NautilusEmptyView, nautilus_empty_view, NAUTILUS_TYPE_FILES_VIEW) static void -nautilus_empty_view_add_file (NautilusView *view, NautilusFile *file, NautilusDirectory *directory) +nautilus_empty_view_add_file (NautilusFilesView *view, NautilusFile *file, NautilusDirectory *directory) { static GTimer *timer = NULL; static gdouble cumu = 0, elaps; @@ -66,122 +66,122 @@ nautilus_empty_view_add_file (NautilusView *view, NautilusFile *file, NautilusDi static void -nautilus_empty_view_begin_loading (NautilusView *view) +nautilus_empty_view_begin_loading (NautilusFilesView *view) { } static void -nautilus_empty_view_clear (NautilusView *view) +nautilus_empty_view_clear (NautilusFilesView *view) { } static void -nautilus_empty_view_file_changed (NautilusView *view, NautilusFile *file, NautilusDirectory *directory) +nautilus_empty_view_file_changed (NautilusFilesView *view, NautilusFile *file, NautilusDirectory *directory) { } static GList * -nautilus_empty_view_get_selection (NautilusView *view) +nautilus_empty_view_get_selection (NautilusFilesView *view) { return NULL; } static GList * -nautilus_empty_view_get_selection_for_file_transfer (NautilusView *view) +nautilus_empty_view_get_selection_for_file_transfer (NautilusFilesView *view) { return NULL; } static gboolean -nautilus_empty_view_is_empty (NautilusView *view) +nautilus_empty_view_is_empty (NautilusFilesView *view) { return NAUTILUS_EMPTY_VIEW (view)->details->number_of_files == 0; } static void -nautilus_empty_view_end_file_changes (NautilusView *view) +nautilus_empty_view_end_file_changes (NautilusFilesView *view) { } static void -nautilus_empty_view_remove_file (NautilusView *view, NautilusFile *file, NautilusDirectory *directory) +nautilus_empty_view_remove_file (NautilusFilesView *view, NautilusFile *file, NautilusDirectory *directory) { NAUTILUS_EMPTY_VIEW (view)->details->number_of_files--; g_assert (NAUTILUS_EMPTY_VIEW (view)->details->number_of_files >= 0); } static void -nautilus_empty_view_set_selection (NautilusView *view, GList *selection) +nautilus_empty_view_set_selection (NautilusFilesView *view, GList *selection) { - nautilus_view_notify_selection_changed (view); + nautilus_files_view_notify_selection_changed (view); } static void -nautilus_empty_view_select_all (NautilusView *view) +nautilus_empty_view_select_all (NautilusFilesView *view) { } static void -nautilus_empty_view_reveal_selection (NautilusView *view) +nautilus_empty_view_reveal_selection (NautilusFilesView *view) { } static void -nautilus_empty_view_merge_menus (NautilusView *view) +nautilus_empty_view_merge_menus (NautilusFilesView *view) { - NAUTILUS_VIEW_CLASS (nautilus_empty_view_parent_class)->merge_menus (view); + NAUTILUS_FILES_VIEW_CLASS (nautilus_empty_view_parent_class)->merge_menus (view); } static void -nautilus_empty_view_update_menus (NautilusView *view) +nautilus_empty_view_update_menus (NautilusFilesView *view) { - NAUTILUS_VIEW_CLASS (nautilus_empty_view_parent_class)->update_menus (view); + NAUTILUS_FILES_VIEW_CLASS (nautilus_empty_view_parent_class)->update_menus (view); } static void -nautilus_empty_view_bump_zoom_level (NautilusView *view, int zoom_increment) +nautilus_empty_view_bump_zoom_level (NautilusFilesView *view, int zoom_increment) { } static NautilusCanvasZoomLevel -nautilus_empty_view_get_zoom_level (NautilusView *view) +nautilus_empty_view_get_zoom_level (NautilusFilesView *view) { return NAUTILUS_CANVAS_ZOOM_LEVEL_STANDARD; } static void -nautilus_empty_view_zoom_to_level (NautilusView *view, +nautilus_empty_view_zoom_to_level (NautilusFilesView *view, NautilusCanvasZoomLevel zoom_level) { } static void -nautilus_empty_view_restore_default_zoom_level (NautilusView *view) +nautilus_empty_view_restore_default_zoom_level (NautilusFilesView *view) { } static gboolean -nautilus_empty_view_can_zoom_in (NautilusView *view) +nautilus_empty_view_can_zoom_in (NautilusFilesView *view) { return FALSE; } static gboolean -nautilus_empty_view_can_zoom_out (NautilusView *view) +nautilus_empty_view_can_zoom_out (NautilusFilesView *view) { return FALSE; } static void -nautilus_empty_view_click_policy_changed (NautilusView *directory_view) +nautilus_empty_view_click_policy_changed (NautilusFilesView *directory_view) { } static int -nautilus_empty_view_compare_files (NautilusView *view, NautilusFile *file1, NautilusFile *file2) +nautilus_empty_view_compare_files (NautilusFilesView *view, NautilusFile *file1, NautilusFile *file2) { if (file1 < file2) { return -1; @@ -195,42 +195,42 @@ nautilus_empty_view_compare_files (NautilusView *view, NautilusFile *file1, Naut } static gboolean -nautilus_empty_view_using_manual_layout (NautilusView *view) +nautilus_empty_view_using_manual_layout (NautilusFilesView *view) { return FALSE; } static void -nautilus_empty_view_end_loading (NautilusView *view, +nautilus_empty_view_end_loading (NautilusFilesView *view, gboolean all_files_seen) { } static char * -nautilus_empty_view_get_first_visible_file (NautilusView *view) +nautilus_empty_view_get_first_visible_file (NautilusFilesView *view) { return NULL; } static void -nautilus_empty_view_scroll_to_file (NautilusView *view, +nautilus_empty_view_scroll_to_file (NautilusFilesView *view, const char *uri) { } static void -nautilus_empty_view_sort_directories_first_changed (NautilusView *view) +nautilus_empty_view_sort_directories_first_changed (NautilusFilesView *view) { } static const char * -nautilus_empty_view_get_id (NautilusView *view) +nautilus_empty_view_get_id (NautilusFilesView *view) { return NAUTILUS_EMPTY_VIEW_ID; } static GIcon* -nautilus_empty_view_get_icon (NautilusView *view) +nautilus_empty_view_get_icon (NautilusFilesView *view) { return NULL; } @@ -238,41 +238,41 @@ nautilus_empty_view_get_icon (NautilusView *view) static void nautilus_empty_view_class_init (NautilusEmptyViewClass *class) { - NautilusViewClass *nautilus_view_class; + NautilusFilesViewClass *nautilus_files_view_class; g_type_class_add_private (class, sizeof (NautilusEmptyViewDetails)); - nautilus_view_class = NAUTILUS_VIEW_CLASS (class); - - nautilus_view_class->add_file = nautilus_empty_view_add_file; - nautilus_view_class->begin_loading = nautilus_empty_view_begin_loading; - nautilus_view_class->bump_zoom_level = nautilus_empty_view_bump_zoom_level; - nautilus_view_class->can_zoom_in = nautilus_empty_view_can_zoom_in; - nautilus_view_class->can_zoom_out = nautilus_empty_view_can_zoom_out; - nautilus_view_class->click_policy_changed = nautilus_empty_view_click_policy_changed; - nautilus_view_class->clear = nautilus_empty_view_clear; - nautilus_view_class->file_changed = nautilus_empty_view_file_changed; - nautilus_view_class->get_selection = nautilus_empty_view_get_selection; - nautilus_view_class->get_selection_for_file_transfer = nautilus_empty_view_get_selection_for_file_transfer; - nautilus_view_class->is_empty = nautilus_empty_view_is_empty; - nautilus_view_class->remove_file = nautilus_empty_view_remove_file; - nautilus_view_class->merge_menus = nautilus_empty_view_merge_menus; - nautilus_view_class->update_menus = nautilus_empty_view_update_menus; - nautilus_view_class->restore_default_zoom_level = nautilus_empty_view_restore_default_zoom_level; - nautilus_view_class->reveal_selection = nautilus_empty_view_reveal_selection; - nautilus_view_class->select_all = nautilus_empty_view_select_all; - nautilus_view_class->set_selection = nautilus_empty_view_set_selection; - nautilus_view_class->compare_files = nautilus_empty_view_compare_files; - nautilus_view_class->sort_directories_first_changed = nautilus_empty_view_sort_directories_first_changed; - nautilus_view_class->get_zoom_level = nautilus_empty_view_get_zoom_level; - nautilus_view_class->zoom_to_level = nautilus_empty_view_zoom_to_level; - nautilus_view_class->end_file_changes = nautilus_empty_view_end_file_changes; - nautilus_view_class->using_manual_layout = nautilus_empty_view_using_manual_layout; - nautilus_view_class->end_loading = nautilus_empty_view_end_loading; - nautilus_view_class->get_view_id = nautilus_empty_view_get_id; - nautilus_view_class->get_first_visible_file = nautilus_empty_view_get_first_visible_file; - nautilus_view_class->scroll_to_file = nautilus_empty_view_scroll_to_file; - nautilus_view_class->get_icon = nautilus_empty_view_get_icon; + nautilus_files_view_class = NAUTILUS_FILES_VIEW_CLASS (class); + + nautilus_files_view_class->add_file = nautilus_empty_view_add_file; + nautilus_files_view_class->begin_loading = nautilus_empty_view_begin_loading; + nautilus_files_view_class->bump_zoom_level = nautilus_empty_view_bump_zoom_level; + nautilus_files_view_class->can_zoom_in = nautilus_empty_view_can_zoom_in; + nautilus_files_view_class->can_zoom_out = nautilus_empty_view_can_zoom_out; + nautilus_files_view_class->click_policy_changed = nautilus_empty_view_click_policy_changed; + nautilus_files_view_class->clear = nautilus_empty_view_clear; + nautilus_files_view_class->file_changed = nautilus_empty_view_file_changed; + nautilus_files_view_class->get_selection = nautilus_empty_view_get_selection; + nautilus_files_view_class->get_selection_for_file_transfer = nautilus_empty_view_get_selection_for_file_transfer; + nautilus_files_view_class->is_empty = nautilus_empty_view_is_empty; + nautilus_files_view_class->remove_file = nautilus_empty_view_remove_file; + nautilus_files_view_class->merge_menus = nautilus_empty_view_merge_menus; + nautilus_files_view_class->update_menus = nautilus_empty_view_update_menus; + nautilus_files_view_class->restore_default_zoom_level = nautilus_empty_view_restore_default_zoom_level; + nautilus_files_view_class->reveal_selection = nautilus_empty_view_reveal_selection; + nautilus_files_view_class->select_all = nautilus_empty_view_select_all; + nautilus_files_view_class->set_selection = nautilus_empty_view_set_selection; + nautilus_files_view_class->compare_files = nautilus_empty_view_compare_files; + nautilus_files_view_class->sort_directories_first_changed = nautilus_empty_view_sort_directories_first_changed; + nautilus_files_view_class->get_zoom_level = nautilus_empty_view_get_zoom_level; + nautilus_files_view_class->zoom_to_level = nautilus_empty_view_zoom_to_level; + nautilus_files_view_class->end_file_changes = nautilus_empty_view_end_file_changes; + nautilus_files_view_class->using_manual_layout = nautilus_empty_view_using_manual_layout; + nautilus_files_view_class->end_loading = nautilus_empty_view_end_loading; + nautilus_files_view_class->get_view_id = nautilus_empty_view_get_id; + nautilus_files_view_class->get_first_visible_file = nautilus_empty_view_get_first_visible_file; + nautilus_files_view_class->scroll_to_file = nautilus_empty_view_scroll_to_file; + nautilus_files_view_class->get_icon = nautilus_empty_view_get_icon; } static void @@ -282,7 +282,7 @@ nautilus_empty_view_init (NautilusEmptyView *empty_view) NautilusEmptyViewDetails); } -NautilusView * +NautilusFilesView * nautilus_empty_view_new (NautilusWindowSlot *slot) { return g_object_new (NAUTILUS_TYPE_EMPTY_VIEW, diff --git a/src/nautilus-empty-view.h b/src/nautilus-empty-view.h index 56ff4e99d..a8c573bb5 100644 --- a/src/nautilus-empty-view.h +++ b/src/nautilus-empty-view.h @@ -24,7 +24,7 @@ #ifndef NAUTILUS_EMPTY_VIEW_H #define NAUTILUS_EMPTY_VIEW_H -#include "nautilus-view.h" +#include "nautilus-files-view.h" #define NAUTILUS_TYPE_EMPTY_VIEW nautilus_empty_view_get_type() #define NAUTILUS_EMPTY_VIEW(obj) \ @@ -41,15 +41,15 @@ typedef struct NautilusEmptyViewDetails NautilusEmptyViewDetails; typedef struct { - NautilusView parent_instance; + NautilusFilesView parent_instance; NautilusEmptyViewDetails *details; } NautilusEmptyView; typedef struct { - NautilusViewClass parent_class; + NautilusFilesViewClass parent_class; } NautilusEmptyViewClass; GType nautilus_empty_view_get_type (void); -NautilusView * nautilus_empty_view_new (NautilusWindowSlot *slot); +NautilusFilesView * nautilus_empty_view_new (NautilusWindowSlot *slot); #endif /* NAUTILUS_EMPTY_VIEW_H */ diff --git a/src/nautilus-view-context-menus.xml b/src/nautilus-files-view-context-menus.xml index df91fb87a..df91fb87a 100644 --- a/src/nautilus-view-context-menus.xml +++ b/src/nautilus-files-view-context-menus.xml diff --git a/src/nautilus-files-view-dnd.c b/src/nautilus-files-view-dnd.c new file mode 100644 index 000000000..90c5b469c --- /dev/null +++ b/src/nautilus-files-view-dnd.c @@ -0,0 +1,547 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ + +/* + * nautilus-view-dnd.c: DnD helpers for NautilusFilesView + * + * Copyright (C) 1999, 2000 Free Software Foundaton + * Copyright (C) 2000, 2001 Eazel, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + * + * Authors: Ettore Perazzoli + * Darin Adler <darin@bentspoon.com> + * John Sullivan <sullivan@eazel.com> + * Pavel Cisler <pavel@eazel.com> + */ + +#include <config.h> + +#include "nautilus-files-view-dnd.h" + +#include "nautilus-files-view.h" + +#include <eel/eel-stock-dialogs.h> +#include <eel/eel-string.h> + +#include <glib/gi18n.h> + +#include <libnautilus-private/nautilus-clipboard.h> +#include <libnautilus-private/nautilus-dnd.h> + +#define GET_ANCESTOR(obj) \ + GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (obj), GTK_TYPE_WINDOW)) + +static inline void +view_widget_to_file_operation_position (NautilusFilesView *view, + GdkPoint *position) +{ + NautilusFilesViewClass *class = NAUTILUS_FILES_VIEW_GET_CLASS (view); + + if (class->widget_to_file_operation_position != NULL) { + class->widget_to_file_operation_position (view, position); + } +} + +static void +view_widget_to_file_operation_position_xy (NautilusFilesView *view, + int *x, + int *y) +{ + GdkPoint position; + + position.x = *x; + position.y = *y; + view_widget_to_file_operation_position (view, &position); + *x = position.x; + *y = position.y; +} + +typedef struct { + NautilusFilesView *view; + char *link_name; + char *target_uri; + char *url; + GdkPoint point; +} NetscapeUrlDropLink; + +static void +revert_slashes (char *string) +{ + while (*string != 0) { + if (*string == '/') { + *string = '\\'; + } + string++; + } +} + +static void +handle_netscape_url_drop_link_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + NetscapeUrlDropLink *data = user_data; + char *link_name = data->link_name; + char *link_display_name; + gint screen_num; + GFileInfo *info; + char *icon_name = NULL; + GdkScreen *screen; + + info = g_file_query_info_finish (G_FILE (source_object), + res, NULL); + + if (info != NULL) { + GIcon *icon; + const char * const *names; + + icon = g_file_info_get_icon (info); + + if (G_IS_THEMED_ICON (icon)) { + names = g_themed_icon_get_names (G_THEMED_ICON (icon)); + icon_name = g_strdup (names[0]); + } + + g_object_unref (info); + } + + if (icon_name == NULL) { + icon_name = g_strdup ("text-html"); + } + + link_display_name = g_strdup_printf (_("Link to %s"), link_name); + + /* The filename can't contain slashes, strip em. + (the basename of http://foo/ is http://foo/) */ + revert_slashes (link_name); + + screen = gtk_widget_get_screen (GTK_WIDGET (data->view)); + screen_num = gdk_screen_get_number (screen); + + nautilus_link_local_create (data->target_uri, + link_name, + link_display_name, + icon_name, + data->url, + &data->point, + screen_num, + TRUE); + + g_free (link_display_name); + g_free (icon_name); + + g_free (data->url); + g_free (data->link_name); + g_free (data->target_uri); + + g_object_unref (data->view); + g_slice_free (NetscapeUrlDropLink, data); +} + +void +nautilus_files_view_handle_netscape_url_drop (NautilusFilesView *view, + const char *encoded_url, + const char *target_uri, + GdkDragAction action, + int x, + int y) +{ + char *url, *title; + char *link_name; + GArray *points; + char **bits; + GList *uri_list = NULL; + GFile *f; + + f = g_file_new_for_uri (target_uri); + + if (!g_file_is_native (f)) { + eel_show_warning_dialog (_("Drag and drop is not supported."), + _("Drag and drop is only supported on local file systems."), + GET_ANCESTOR (view)); + g_object_unref (f); + return; + } + + g_object_unref (f); + + /* _NETSCAPE_URL_ works like this: $URL\n$TITLE */ + bits = g_strsplit (encoded_url, "\n", 0); + switch (g_strv_length (bits)) { + case 0: + g_strfreev (bits); + return; + case 1: + url = bits[0]; + title = NULL; + break; + default: + url = bits[0]; + title = bits[1]; + } + + f = g_file_new_for_uri (url); + + view_widget_to_file_operation_position_xy (view, &x, &y); + + /* We don't support GDK_ACTION_ASK or GDK_ACTION_PRIVATE + * and we don't support combinations either. */ + if ((action != GDK_ACTION_DEFAULT) && + (action != GDK_ACTION_COPY) && + (action != GDK_ACTION_MOVE) && + (action != GDK_ACTION_LINK)) { + eel_show_warning_dialog (_("Drag and drop is not supported."), + _("An invalid drag type was used."), + GET_ANCESTOR (view)); + return; + } + + if (action == GDK_ACTION_LINK) { + if (g_strcmp0 (title, NULL) == 0) { + link_name = g_file_get_basename (f); + } else { + link_name = g_strdup (title); + } + + if (g_strcmp0 (link_name, NULL) != 0) { + NetscapeUrlDropLink *data; + + data = g_slice_new0 (NetscapeUrlDropLink); + data->link_name = link_name; + data->point.x = x; + data->point.y = y; + data->view = g_object_ref (view); + data->target_uri = g_strdup (target_uri); + data->url = g_strdup (url); + + g_file_query_info_async (f, + G_FILE_ATTRIBUTE_STANDARD_ICON, + 0, 0, NULL, + handle_netscape_url_drop_link_cb, + data); + } + } else { + GdkPoint tmp_point = { 0, 0 }; + + /* pass in a 1-item array of icon positions, relative to x, y */ + points = g_array_new (FALSE, TRUE, sizeof (GdkPoint)); + g_array_append_val (points, tmp_point); + + uri_list = g_list_append (uri_list, url); + + nautilus_files_view_move_copy_items (view, uri_list, points, + target_uri, + action, x, y); + + g_list_free (uri_list); + g_array_free (points, TRUE); + } + + g_object_unref (f); + g_strfreev (bits); +} + +void +nautilus_files_view_handle_uri_list_drop (NautilusFilesView *view, + const char *item_uris, + const char *target_uri, + GdkDragAction action, + int x, + int y) +{ + gchar **uri_list; + GList *real_uri_list = NULL; + char *container_uri; + int n_uris, i; + GArray *points; + + if (item_uris == NULL) { + return; + } + + container_uri = NULL; + if (target_uri == NULL) { + container_uri = nautilus_files_view_get_backing_uri (view); + g_assert (container_uri != NULL); + } + + if (action == GDK_ACTION_ASK) { + action = nautilus_drag_drop_action_ask + (GTK_WIDGET (view), + GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK); + if (action == 0) { + g_free (container_uri); + return; + } + } + + /* We don't support GDK_ACTION_ASK or GDK_ACTION_PRIVATE + * and we don't support combinations either. */ + if ((action != GDK_ACTION_DEFAULT) && + (action != GDK_ACTION_COPY) && + (action != GDK_ACTION_MOVE) && + (action != GDK_ACTION_LINK)) { + eel_show_warning_dialog (_("Drag and drop is not supported."), + _("An invalid drag type was used."), + GET_ANCESTOR (view)); + g_free (container_uri); + return; + } + + n_uris = 0; + uri_list = g_uri_list_extract_uris (item_uris); + for (i = 0; uri_list[i] != NULL; i++) { + real_uri_list = g_list_append (real_uri_list, uri_list[i]); + n_uris++; + } + g_free (uri_list); + + /* do nothing if no real uris are left */ + if (n_uris == 0) { + g_free (container_uri); + return; + } + + if (n_uris == 1) { + GdkPoint tmp_point = { 0, 0 }; + + /* pass in a 1-item array of icon positions, relative to x, y */ + points = g_array_new (FALSE, TRUE, sizeof (GdkPoint)); + g_array_append_val (points, tmp_point); + } else { + points = NULL; + } + + view_widget_to_file_operation_position_xy (view, &x, &y); + + nautilus_files_view_move_copy_items (view, real_uri_list, points, + target_uri != NULL ? target_uri : container_uri, + action, x, y); + + g_list_free_full (real_uri_list, g_free); + + if (points != NULL) + g_array_free (points, TRUE); + + g_free (container_uri); +} + +#define MAX_LEN_FILENAME 128 +#define MIN_LEN_FILENAME 10 + +static char * +get_drop_filename (const char *text) +{ + char *filename; + char trimmed[MAX_LEN_FILENAME]; + int i; + int last_word = -1; + int last_sentence = -1; + int last_nonspace = -1; + int num_attrs; + PangoLogAttr *attrs; + gchar *current_char; + + num_attrs = MIN (g_utf8_strlen (text, -1), MAX_LEN_FILENAME) + 1; + attrs = g_new (PangoLogAttr, num_attrs); + g_utf8_strncpy (trimmed, text, num_attrs - 1); + pango_get_log_attrs (trimmed, -1, -1, pango_language_get_default (), attrs, num_attrs); + + /* since the end of the text will always match a word boundary don't include it */ + for (i = 0; (i < num_attrs - 1); i++) { + if (!attrs[i].is_white) + last_nonspace = i; + if (attrs[i].is_sentence_end) + last_sentence = last_nonspace; + if (attrs[i].is_word_boundary) + last_word = last_nonspace; + } + g_free (attrs); + + if (last_sentence > 0) + i = last_sentence; + else + i = last_word; + + if (i > MIN_LEN_FILENAME) { + char basename[MAX_LEN_FILENAME]; + g_utf8_strncpy (basename, trimmed, i); + filename = g_strdup_printf ("%s.txt", basename); + } else { + /* Translator: This is the filename used for when you dnd text to a directory */ + filename = g_strdup (_("Dropped Text.txt")); + } + + /* Remove any invalid characters */ + for (current_char = filename; + *current_char; + current_char = g_utf8_next_char (current_char)) { + if ( G_IS_DIR_SEPARATOR ( g_utf8_get_char (current_char))) { + *current_char = '-'; + } + } + + return filename; +} + +void +nautilus_files_view_handle_text_drop (NautilusFilesView *view, + const char *text, + const char *target_uri, + GdkDragAction action, + int x, + int y) +{ + int length; + char *container_uri; + GdkPoint pos; + char *filename; + + if (text == NULL) { + return; + } + + g_return_if_fail (action == GDK_ACTION_COPY); + + container_uri = NULL; + if (target_uri == NULL) { + container_uri = nautilus_files_view_get_backing_uri (view); + g_assert (container_uri != NULL); + } + + length = strlen (text); + + pos.x = x; + pos.y = y; + view_widget_to_file_operation_position (view, &pos); + + /* try to get text to use as a filename */ + filename = get_drop_filename (text); + + nautilus_files_view_new_file_with_initial_contents (view, + target_uri != NULL ? target_uri : container_uri, + filename, + text, + length, + &pos); + g_free (filename); + g_free (container_uri); +} + +void +nautilus_files_view_handle_raw_drop (NautilusFilesView *view, + const char *raw_data, + int length, + const char *target_uri, + const char *direct_save_uri, + GdkDragAction action, + int x, + int y) +{ + char *container_uri, *filename; + GFile *direct_save_full; + GdkPoint pos; + + if (raw_data == NULL) { + return; + } + + g_return_if_fail (action == GDK_ACTION_COPY); + + container_uri = NULL; + if (target_uri == NULL) { + container_uri = nautilus_files_view_get_backing_uri (view); + g_assert (container_uri != NULL); + } + + pos.x = x; + pos.y = y; + view_widget_to_file_operation_position (view, &pos); + + filename = NULL; + if (direct_save_uri != NULL) { + direct_save_full = g_file_new_for_uri (direct_save_uri); + filename = g_file_get_basename (direct_save_full); + } + if (filename == NULL) { + /* Translator: This is the filename used for when you dnd raw + * data to a directory, if the source didn't supply a name. + */ + filename = g_strdup (_("dropped data")); + } + + nautilus_files_view_new_file_with_initial_contents ( + view, target_uri != NULL ? target_uri : container_uri, + filename, raw_data, length, &pos); + + g_free (container_uri); + g_free (filename); +} + +void +nautilus_files_view_drop_proxy_received_uris (NautilusFilesView *view, + const GList *source_uri_list, + const char *target_uri, + GdkDragAction action) +{ + char *container_uri; + + container_uri = NULL; + if (target_uri == NULL) { + container_uri = nautilus_files_view_get_backing_uri (view); + g_assert (container_uri != NULL); + } + + if (action == GDK_ACTION_ASK) { + action = nautilus_drag_drop_action_ask + (GTK_WIDGET (view), + GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK); + if (action == 0) { + return; + } + } + + nautilus_clipboard_clear_if_colliding_uris (GTK_WIDGET (view), + source_uri_list, + nautilus_files_view_get_copied_files_atom (view)); + + nautilus_files_view_move_copy_items (view, source_uri_list, NULL, + target_uri != NULL ? target_uri : container_uri, + action, 0, 0); + + g_free (container_uri); +} + +void +nautilus_files_view_handle_hover (NautilusFilesView *view, + const char *target_uri) +{ + NautilusWindowSlot *slot; + GFile *location; + GFile *current_location; + NautilusFile *target_file; + gboolean target_is_dir; + + slot = nautilus_files_view_get_nautilus_window_slot (view); + + location = g_file_new_for_uri (target_uri); + target_file = nautilus_file_get_existing (location); + target_is_dir = nautilus_file_get_file_type (target_file) == G_FILE_TYPE_DIRECTORY; + current_location = nautilus_window_slot_get_location (slot); + if (target_is_dir && ! (current_location != NULL && g_file_equal(location, current_location))) { + nautilus_window_slot_open_location (slot, location, 0); + } + g_object_unref (location); + nautilus_file_unref (target_file); +} diff --git a/src/nautilus-files-view-dnd.h b/src/nautilus-files-view-dnd.h new file mode 100644 index 000000000..1f123582b --- /dev/null +++ b/src/nautilus-files-view-dnd.h @@ -0,0 +1,68 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ + +/* + * nautilus-view-dnd.h: DnD helpers for NautilusFilesView + * + * Copyright (C) 1999, 2000 Free Software Foundaton + * Copyright (C) 2000, 2001 Eazel, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + * + * Authors: Ettore Perazzoli + * Darin Adler <darin@bentspoon.com> + * John Sullivan <sullivan@eazel.com> + * Pavel Cisler <pavel@eazel.com> + */ + +#ifndef __NAUTILUS_FILES_VIEW_DND_H__ +#define __NAUTILUS_FILES_VIEW_DND_H__ + +#include "nautilus-files-view.h" + +void nautilus_files_view_handle_netscape_url_drop (NautilusFilesView *view, + const char *encoded_url, + const char *target_uri, + GdkDragAction action, + int x, + int y); +void nautilus_files_view_handle_uri_list_drop (NautilusFilesView *view, + const char *item_uris, + const char *target_uri, + GdkDragAction action, + int x, + int y); +void nautilus_files_view_handle_text_drop (NautilusFilesView *view, + const char *text, + const char *target_uri, + GdkDragAction action, + int x, + int y); +void nautilus_files_view_handle_raw_drop (NautilusFilesView *view, + const char *raw_data, + int length, + const char *target_uri, + const char *direct_save_uri, + GdkDragAction action, + int x, + int y); +void nautilus_files_view_handle_hover (NautilusFilesView *view, + const char *target_uri); + +void nautilus_files_view_drop_proxy_received_uris (NautilusFilesView *view, + const GList *uris, + const char *target_location, + GdkDragAction action); + + +#endif /* __NAUTILUS_FILES_VIEW_DND_H__ */ diff --git a/src/nautilus-files-view.c b/src/nautilus-files-view.c new file mode 100644 index 000000000..a6c5c7510 --- /dev/null +++ b/src/nautilus-files-view.c @@ -0,0 +1,8147 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ + +/* nautilus-files-view.c + * + * Copyright (C) 1999, 2000 Free Software Foundation + * Copyright (C) 2000, 2001 Eazel, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + * + * Authors: Ettore Perazzoli, + * John Sullivan <sullivan@eazel.com>, + * Darin Adler <darin@bentspoon.com>, + * Pavel Cisler <pavel@eazel.com>, + * David Emory Watson <dwatson@cs.ucr.edu> + */ + +#include <config.h> + +#include "nautilus-files-view.h" + +#include "nautilus-application.h" +#include "nautilus-desktop-canvas-view.h" +#include "nautilus-error-reporting.h" +#include "nautilus-floating-bar.h" +#include "nautilus-list-view.h" +#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" +#endif + +#ifdef HAVE_X11_XF86KEYSYM_H +#include <X11/XF86keysym.h> +#endif + +#include <gdk/gdkx.h> +#include <gdk/gdkkeysyms.h> +#include <gtk/gtk.h> +#include <glib/gi18n.h> +#include <glib/gstdio.h> +#include <gio/gio.h> +#include <math.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include <eel/eel-glib-extensions.h> +#include <eel/eel-gnome-extensions.h> +#include <eel/eel-gtk-extensions.h> +#include <eel/eel-stock-dialogs.h> +#include <eel/eel-string.h> +#include <eel/eel-vfs-extensions.h> + +#include <libnautilus-extension/nautilus-menu-provider.h> +#include <libnautilus-private/nautilus-clipboard.h> +#include <libnautilus-private/nautilus-clipboard-monitor.h> +#include <libnautilus-private/nautilus-desktop-icon-file.h> +#include <libnautilus-private/nautilus-desktop-directory.h> +#include <libnautilus-private/nautilus-search-directory.h> +#include <libnautilus-private/nautilus-directory.h> +#include <libnautilus-private/nautilus-dnd.h> +#include <libnautilus-private/nautilus-file-attributes.h> +#include <libnautilus-private/nautilus-file-changes-queue.h> +#include <libnautilus-private/nautilus-file-dnd.h> +#include <libnautilus-private/nautilus-file-operations.h> +#include <libnautilus-private/nautilus-file-utilities.h> +#include <libnautilus-private/nautilus-file-private.h> +#include <libnautilus-private/nautilus-global-preferences.h> +#include <libnautilus-private/nautilus-link.h> +#include <libnautilus-private/nautilus-metadata.h> +#include <libnautilus-private/nautilus-recent.h> +#include <libnautilus-private/nautilus-module.h> +#include <libnautilus-private/nautilus-profile.h> +#include <libnautilus-private/nautilus-program-choosing.h> +#include <libnautilus-private/nautilus-trash-monitor.h> +#include <libnautilus-private/nautilus-ui-utilities.h> +#include <libnautilus-private/nautilus-signaller.h> +#include <libnautilus-private/nautilus-icon-names.h> + +#define GNOME_DESKTOP_USE_UNSTABLE_API +#include <gdesktop-enums.h> + +#define DEBUG_FLAG NAUTILUS_DEBUG_DIRECTORY_VIEW +#include <libnautilus-private/nautilus-debug.h> + +/* Minimum starting update inverval */ +#define UPDATE_INTERVAL_MIN 100 +/* Maximum update interval */ +#define UPDATE_INTERVAL_MAX 2000 +/* Amount of miliseconds the update interval is increased */ +#define UPDATE_INTERVAL_INC 250 +/* Interval at which the update interval is increased */ +#define UPDATE_INTERVAL_TIMEOUT_INTERVAL 250 +/* Milliseconds that have to pass without a change to reset the update interval */ +#define UPDATE_INTERVAL_RESET 1000 + +#define SILENT_WINDOW_OPEN_LIMIT 5 + +#define DUPLICATE_HORIZONTAL_ICON_OFFSET 70 +#define DUPLICATE_VERTICAL_ICON_OFFSET 30 + +#define MAX_QUEUED_UPDATES 500 + +#define MAX_MENU_LEVELS 5 +#define TEMPLATE_LIMIT 30 + +/* Delay to show the duplicated label when creating a folder */ +#define FILE_NAME_DUPLICATED_LABEL_TIMEOUT 500 + +/* Delay to show the Loading... floating bar */ +#define FLOATING_BAR_LOADING_DELAY 500 /* ms */ + +enum { + ADD_FILE, + BEGIN_FILE_CHANGES, + BEGIN_LOADING, + CLEAR, + END_FILE_CHANGES, + END_LOADING, + FILE_CHANGED, + MOVE_COPY_ITEMS, + REMOVE_FILE, + SELECTION_CHANGED, + TRASH, + DELETE, + LAST_SIGNAL +}; + +enum { + PROP_WINDOW_SLOT = 1, + PROP_SUPPORTS_ZOOMING, + PROP_ICON, + PROP_VIEW_WIDGET, + NUM_PROPERTIES +}; + +static guint signals[LAST_SIGNAL]; +static GParamSpec *properties[NUM_PROPERTIES] = { NULL, }; + +static GdkAtom copied_files_atom; + +static char *scripts_directory_uri = NULL; +static int scripts_directory_uri_length; + +struct NautilusFilesViewDetails +{ + NautilusWindowSlot *slot; + NautilusDirectory *model; + NautilusFile *directory_as_file; + guint dir_merge_id; + + gint duplicated_label_timeout_id; + GtkWidget *rename_file_popover; + + gboolean supports_zooming; + + GList *scripts_directory_list; + GList *templates_directory_list; + + guint display_selection_idle_id; + guint update_context_menus_timeout_id; + guint update_status_idle_id; + guint reveal_selection_idle_id; + + guint display_pending_source_id; + guint changes_timeout_id; + + guint update_interval; + guint64 last_queued; + + guint files_added_handler_id; + guint files_changed_handler_id; + guint load_error_handler_id; + guint done_loading_handler_id; + guint file_changed_handler_id; + + GList *new_added_files; + GList *new_changed_files; + + GHashTable *non_ready_files; + + GList *old_added_files; + GList *old_changed_files; + + GList *pending_selection; + + /* whether we are in the active slot */ + gboolean active; + + /* loading indicates whether this view has begun loading a directory. + * This flag should need not be set inside subclasses. NautilusFilesView automatically + * sets 'loading' to TRUE before it begins loading a directory's contents and to FALSE + * after it finishes loading the directory and its view. + */ + gboolean loading; + gboolean templates_present; + gboolean scripts_present; + + gboolean sort_directories_first; + + gboolean show_foreign_files; + gboolean show_hidden_files; + gboolean ignore_hidden_file_preferences; + + gboolean batching_selection_level; + gboolean selection_changed_while_batched; + + gboolean selection_was_removed; + + gboolean metadata_for_directory_as_file_pending; + gboolean metadata_for_files_in_directory_pending; + + GList *subdirectory_list; + + GdkPoint context_menu_position; + + GMenu *selection_menu; + GMenu *background_menu; + + GActionGroup *view_action_group; + + GtkWidget *scrolled_window; + + /* Empty states */ + GtkWidget *folder_is_empty_widget; + GtkWidget *no_search_results_widget; + + /* Floating bar */ + guint floating_bar_set_status_timeout_id; + guint floating_bar_loading_timeout_id; + GtkWidget *floating_bar; + + /* View menu */ + GtkWidget *view_menu_widget; + GtkWidget *view_icon; + GtkWidget *sort_menu; + GtkWidget *sort_trash_time; + GtkWidget *sort_search_relevance; + GtkWidget *visible_columns; + GtkWidget *stop; + GtkWidget *reload; + GtkAdjustment *zoom_adjustment; + GtkWidget *zoom_level_scale; + + gulong stop_signal_handler; + gulong reload_signal_handler; +}; + +typedef struct { + NautilusFile *file; + NautilusDirectory *directory; +} FileAndDirectory; + +/* forward declarations */ + +static gboolean display_selection_info_idle_callback (gpointer data); +static void trash_or_delete_files (GtkWindow *parent_window, + const GList *files, + NautilusFilesView *view); +static void load_directory (NautilusFilesView *view, + NautilusDirectory *directory); +static void clipboard_changed_callback (NautilusClipboardMonitor *monitor, + NautilusFilesView *view); +static void open_one_in_new_window (gpointer data, + gpointer callback_data); +static void schedule_update_context_menus (NautilusFilesView *view); +static void remove_update_context_menus_timeout_callback (NautilusFilesView *view); +static void schedule_update_status (NautilusFilesView *view); +static void remove_update_status_idle_callback (NautilusFilesView *view); +static void reset_update_interval (NautilusFilesView *view); +static void schedule_idle_display_of_pending_files (NautilusFilesView *view); +static void unschedule_display_of_pending_files (NautilusFilesView *view); +static void disconnect_model_handlers (NautilusFilesView *view); +static void metadata_for_directory_as_file_ready_callback (NautilusFile *file, + gpointer callback_data); +static void metadata_for_files_in_directory_ready_callback (NautilusDirectory *directory, + GList *files, + gpointer callback_data); +static void nautilus_files_view_trash_state_changed_callback (NautilusTrashMonitor *trash, + gboolean state, + gpointer callback_data); +static void nautilus_files_view_select_file (NautilusFilesView *view, + NautilusFile *file); + +static void update_templates_directory (NautilusFilesView *view); + +static void check_empty_states (NautilusFilesView *view); + +G_DEFINE_TYPE (NautilusFilesView, nautilus_files_view, GTK_TYPE_OVERLAY); + +static const struct { + unsigned int keyval; + const char *action; +} extra_view_keybindings [] = { +#ifdef HAVE_X11_XF86KEYSYM_H + /* View actions */ + { XF86XK_ZoomIn, "zoom-in" }, + { XF86XK_ZoomOut, "zoom-out" }, + +#endif +}; + +static void +check_empty_states (NautilusFilesView *view) +{ + GList *files; + GList *filtered; + gboolean show_hidden_files; + + gtk_widget_hide (view->details->no_search_results_widget); + gtk_widget_hide (view->details->folder_is_empty_widget); + if (!view->details->loading && view->details->model) { + files = nautilus_directory_get_file_list (view->details->model); + show_hidden_files = g_settings_get_boolean (gtk_filechooser_preferences, + NAUTILUS_PREFERENCES_SHOW_HIDDEN_FILES); + filtered = nautilus_file_list_filter_hidden (files, show_hidden_files); + if (g_list_length (filtered) == 0) { + if (nautilus_files_view_is_search (view)) { + gtk_widget_show (view->details->no_search_results_widget); + } else { + gtk_widget_show (view->details->folder_is_empty_widget); + } + } + nautilus_file_list_unref (filtered); + nautilus_file_list_unref (files); + } +} + +/* + * Floating Bar code + */ +static void +remove_loading_floating_bar (NautilusFilesView *view) +{ + if (view->details->floating_bar_loading_timeout_id != 0) { + g_source_remove (view->details->floating_bar_loading_timeout_id); + view->details->floating_bar_loading_timeout_id = 0; + } + + gtk_widget_hide (view->details->floating_bar); + nautilus_floating_bar_cleanup_actions (NAUTILUS_FLOATING_BAR (view->details->floating_bar)); +} + +static void +real_setup_loading_floating_bar (NautilusFilesView *view) +{ + gboolean disable_chrome; + + g_object_get (nautilus_files_view_get_window (view), + "disable-chrome", &disable_chrome, + NULL); + + if (disable_chrome) { + gtk_widget_hide (view->details->floating_bar); + return; + } + + nautilus_floating_bar_cleanup_actions (NAUTILUS_FLOATING_BAR (view->details->floating_bar)); + nautilus_floating_bar_set_primary_label (NAUTILUS_FLOATING_BAR (view->details->floating_bar), + nautilus_files_view_is_search (view) ? _("Searching…") : _("Loading…")); + nautilus_floating_bar_set_details_label (NAUTILUS_FLOATING_BAR (view->details->floating_bar), NULL); + nautilus_floating_bar_set_show_spinner (NAUTILUS_FLOATING_BAR (view->details->floating_bar), view->details->loading); + nautilus_floating_bar_add_action (NAUTILUS_FLOATING_BAR (view->details->floating_bar), + "process-stop-symbolic", + NAUTILUS_FLOATING_BAR_ACTION_ID_STOP); + + gtk_widget_set_halign (view->details->floating_bar, GTK_ALIGN_END); + gtk_widget_show (view->details->floating_bar); +} + +static gboolean +setup_loading_floating_bar_timeout_cb (gpointer user_data) +{ + NautilusFilesView *view = user_data; + + view->details->floating_bar_loading_timeout_id = 0; + real_setup_loading_floating_bar (view); + + return FALSE; +} + +static void +setup_loading_floating_bar (NautilusFilesView *view) +{ + /* setup loading overlay */ + if (view->details->floating_bar_set_status_timeout_id != 0) { + g_source_remove (view->details->floating_bar_set_status_timeout_id); + view->details->floating_bar_set_status_timeout_id = 0; + } + + if (view->details->floating_bar_loading_timeout_id != 0) { + g_source_remove (view->details->floating_bar_loading_timeout_id); + view->details->floating_bar_loading_timeout_id = 0; + } + + view->details->floating_bar_loading_timeout_id = + g_timeout_add (FLOATING_BAR_LOADING_DELAY, setup_loading_floating_bar_timeout_cb, view); +} + +static void +floating_bar_action_cb (NautilusFloatingBar *floating_bar, + gint action, + NautilusFilesView *view) +{ + if (action == NAUTILUS_FLOATING_BAR_ACTION_ID_STOP) { + remove_loading_floating_bar (view); + nautilus_window_slot_stop_loading (view->details->slot); + } +} + +static void +real_floating_bar_set_short_status (NautilusFilesView *view, + const gchar *primary_status, + const gchar *detail_status) +{ + gboolean disable_chrome; + + nautilus_floating_bar_cleanup_actions (NAUTILUS_FLOATING_BAR (view->details->floating_bar)); + nautilus_floating_bar_set_show_spinner (NAUTILUS_FLOATING_BAR (view->details->floating_bar), view->details->loading); + + g_object_get (nautilus_files_view_get_window (view), + "disable-chrome", &disable_chrome, + NULL); + + if ((primary_status == NULL && detail_status == NULL) || disable_chrome) { + gtk_widget_hide (view->details->floating_bar); + return; + } + + nautilus_floating_bar_set_labels (NAUTILUS_FLOATING_BAR (view->details->floating_bar), + primary_status, + detail_status); + + gtk_widget_show (view->details->floating_bar); +} + +typedef struct { + gchar *primary_status; + gchar *detail_status; + NautilusFilesView *view; +} FloatingBarSetStatusData; + +static void +floating_bar_set_status_data_free (gpointer data) +{ + FloatingBarSetStatusData *status_data = data; + + g_free (status_data->primary_status); + g_free (status_data->detail_status); + + g_slice_free (FloatingBarSetStatusData, data); +} + +static gboolean +floating_bar_set_status_timeout_cb (gpointer data) +{ + FloatingBarSetStatusData *status_data = data; + + status_data->view->details->floating_bar_set_status_timeout_id = 0; + real_floating_bar_set_short_status (status_data->view, + status_data->primary_status, + status_data->detail_status); + + return FALSE; +} + +static void +set_floating_bar_status (NautilusFilesView *view, + const gchar *primary_status, + const gchar *detail_status) +{ + GtkSettings *settings; + gint double_click_time; + FloatingBarSetStatusData *status_data; + + if (view->details->floating_bar_set_status_timeout_id != 0) { + g_source_remove (view->details->floating_bar_set_status_timeout_id); + view->details->floating_bar_set_status_timeout_id = 0; + } + + settings = gtk_settings_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (view))); + g_object_get (settings, + "gtk-double-click-time", &double_click_time, + NULL); + + status_data = g_slice_new0 (FloatingBarSetStatusData); + status_data->primary_status = g_strdup (primary_status); + status_data->detail_status = g_strdup (detail_status); + status_data->view = view; + + /* waiting for half of the double-click-time before setting + * the status seems to be a good approximation of not setting it + * too often and not delaying the statusbar too much. + */ + view->details->floating_bar_set_status_timeout_id = + g_timeout_add_full (G_PRIORITY_DEFAULT, + (guint) (double_click_time / 2), + floating_bar_set_status_timeout_cb, + status_data, + floating_bar_set_status_data_free); +} + +static char * +real_get_backing_uri (NautilusFilesView *view) +{ + NautilusDirectory *directory; + char *uri; + + g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), NULL); + + if (view->details->model == NULL) { + return NULL; + } + + directory = view->details->model; + + if (NAUTILUS_IS_DESKTOP_DIRECTORY (directory)) { + directory = nautilus_desktop_directory_get_real_directory (NAUTILUS_DESKTOP_DIRECTORY (directory)); + } else { + nautilus_directory_ref (directory); + } + + uri = nautilus_directory_get_uri (directory); + + nautilus_directory_unref (directory); + + return uri; +} + +/** + * + * nautilus_files_view_get_backing_uri: + * + * Returns the URI for the target location of new directory, new file, new + * link and paste operations. + */ + +char * +nautilus_files_view_get_backing_uri (NautilusFilesView *view) +{ + g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), NULL); + + return NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->get_backing_uri (view); +} + +/** + * nautilus_files_view_select_all: + * + * select all the items in the view + * + **/ +static void +nautilus_files_view_select_all (NautilusFilesView *view) +{ + g_return_if_fail (NAUTILUS_IS_FILES_VIEW (view)); + + NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->select_all (view); +} + +static void +nautilus_files_view_select_first (NautilusFilesView *view) +{ + g_return_if_fail (NAUTILUS_IS_FILES_VIEW (view)); + + NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->select_first (view); +} + +static void +nautilus_files_view_call_set_selection (NautilusFilesView *view, GList *selection) +{ + g_return_if_fail (NAUTILUS_IS_FILES_VIEW (view)); + + NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->set_selection (view, selection); +} + +static GList * +nautilus_files_view_get_selection_for_file_transfer (NautilusFilesView *view) +{ + g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), NULL); + + return NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->get_selection_for_file_transfer (view); +} + +static void +nautilus_files_view_invert_selection (NautilusFilesView *view) +{ + g_return_if_fail (NAUTILUS_IS_FILES_VIEW (view)); + + NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->invert_selection (view); +} + +/** + * nautilus_files_view_reveal_selection: + * + * Scroll as necessary to reveal the selected items. + **/ +static void +nautilus_files_view_reveal_selection (NautilusFilesView *view) +{ + g_return_if_fail (NAUTILUS_IS_FILES_VIEW (view)); + + NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->reveal_selection (view); +} + +static gboolean +nautilus_files_view_using_manual_layout (NautilusFilesView *view) +{ + g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), FALSE); + + return NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->using_manual_layout (view); +} + +/** + * nautilus_files_view_get_icon: + * @view: a #NautilusFilesView + * + * Retrieves the #GIcon that represents @view. + * + * Returns: (transfer none): the #Gicon that represents @view + */ +GIcon* +nautilus_files_view_get_icon (NautilusFilesView *view) +{ + g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), NULL); + + return NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->get_icon (view); +} + +/** + * nautilus_files_view_get_view_widget: + * @view: a #NautilusFilesView + * + * Retrieves the view menu, as a #GtkWidget. If it's %NULL, + * the button renders insensitive. + * + * Returns: (transfer none): a #GtkWidget for the view menu + */ +GtkWidget* +nautilus_files_view_get_view_widget (NautilusFilesView *view) +{ + g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), NULL); + + return view->details->view_menu_widget; +} + +/** + * nautilus_files_view_can_rename_file + * + * Determine whether a file can be renamed. + * @file: A NautilusFile + * + * Return value: TRUE if @file can be renamed, FALSE otherwise. + * + **/ +static gboolean +nautilus_files_view_can_rename_file (NautilusFilesView *view, + NautilusFile *file) +{ + return NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->can_rename_file (view, file); +} + +static gboolean +nautilus_files_view_is_read_only (NautilusFilesView *view) +{ + g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), FALSE); + + return NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->is_read_only (view); +} + +static gboolean +showing_trash_directory (NautilusFilesView *view) +{ + NautilusFile *file; + + file = nautilus_files_view_get_directory_as_file (view); + if (file != NULL) { + return nautilus_file_is_in_trash (file); + } + return FALSE; +} + +static gboolean +showing_network_directory (NautilusFilesView *view) +{ + NautilusFile *file; + + file = nautilus_files_view_get_directory_as_file (view); + if (file != NULL) { + return nautilus_file_is_in_network (file); + } + return FALSE; +} + +static gboolean +showing_recent_directory (NautilusFilesView *view) +{ + NautilusFile *file; + + file = nautilus_files_view_get_directory_as_file (view); + if (file != NULL) { + return nautilus_file_is_in_recent (file); + } + return FALSE; +} + +static gboolean +nautilus_files_view_supports_creating_files (NautilusFilesView *view) +{ + g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), FALSE); + + return !nautilus_files_view_is_read_only (view) + && !showing_trash_directory (view) + && !showing_recent_directory (view); +} + +static gboolean +nautilus_files_view_is_empty (NautilusFilesView *view) +{ + g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), FALSE); + + return NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->is_empty (view); +} + +/** + * nautilus_files_view_bump_zoom_level: + * + * bump the current zoom level by invoking the relevant subclass through the slot + * + **/ +void +nautilus_files_view_bump_zoom_level (NautilusFilesView *view, + int zoom_increment) +{ + g_return_if_fail (NAUTILUS_IS_FILES_VIEW (view)); + + if (!nautilus_files_view_supports_zooming (view)) { + return; + } + + NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->bump_zoom_level (view, zoom_increment); +} + +/** + * nautilus_files_view_can_zoom_in: + * + * Determine whether the view can be zoomed any closer. + * @view: The zoomable NautilusFilesView. + * + * Return value: TRUE if @view can be zoomed any closer, FALSE otherwise. + * + **/ +gboolean +nautilus_files_view_can_zoom_in (NautilusFilesView *view) +{ + g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), FALSE); + + if (!nautilus_files_view_supports_zooming (view)) { + return FALSE; + } + + return NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->can_zoom_in (view); +} + +/** + * nautilus_files_view_can_zoom_out: + * + * Determine whether the view can be zoomed any further away. + * @view: The zoomable NautilusFilesView. + * + * Return value: TRUE if @view can be zoomed any further away, FALSE otherwise. + * + **/ +gboolean +nautilus_files_view_can_zoom_out (NautilusFilesView *view) +{ + g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), FALSE); + + if (!nautilus_files_view_supports_zooming (view)) { + return FALSE; + } + + return NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->can_zoom_out (view); +} + +gboolean +nautilus_files_view_supports_zooming (NautilusFilesView *view) +{ + g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), FALSE); + + return view->details->supports_zooming; +} + +/** + * nautilus_files_view_restore_default_zoom_level: + * + * restore to the default zoom level by invoking the relevant subclass through the slot + * + **/ +void +nautilus_files_view_restore_default_zoom_level (NautilusFilesView *view) +{ + g_return_if_fail (NAUTILUS_IS_FILES_VIEW (view)); + + if (!nautilus_files_view_supports_zooming (view)) { + return; + } + + NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->restore_default_zoom_level (view); +} + +gboolean +nautilus_files_view_is_search (NautilusFilesView *view) +{ + if (!view->details->model) + return FALSE; + + return NAUTILUS_IS_SEARCH_DIRECTORY (view->details->model); +} + +const char * +nautilus_files_view_get_view_id (NautilusFilesView *view) +{ + return NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->get_view_id (view); +} + +char * +nautilus_files_view_get_first_visible_file (NautilusFilesView *view) +{ + return NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->get_first_visible_file (view); +} + +void +nautilus_files_view_scroll_to_file (NautilusFilesView *view, + const char *uri) +{ + NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->scroll_to_file (view, uri); +} + +/** + * nautilus_files_view_get_selection: + * + * Get a list of NautilusFile pointers that represents the + * currently-selected items in this view. Subclasses must override + * the signal handler for the 'get_selection' signal. Callers are + * responsible for g_free-ing the list (but not its data). + * @view: NautilusFilesView whose selected items are of interest. + * + * Return value: GList of NautilusFile pointers representing the selection. + * + **/ +GList * +nautilus_files_view_get_selection (NautilusFilesView *view) +{ + g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), NULL); + + return NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->get_selection (view); +} + +typedef struct { + NautilusFile *file; + NautilusFilesView *directory_view; +} ScriptLaunchParameters; + +typedef struct { + NautilusFile *file; + NautilusFilesView *directory_view; +} CreateTemplateParameters; + +static GList * +file_and_directory_list_to_files (GList *fad_list) +{ + GList *res, *l; + FileAndDirectory *fad; + + res = NULL; + for (l = fad_list; l != NULL; l = l->next) { + fad = l->data; + res = g_list_prepend (res, nautilus_file_ref (fad->file)); + } + return g_list_reverse (res); +} + + +static GList * +file_and_directory_list_from_files (NautilusDirectory *directory, + GList *files) +{ + GList *res, *l; + FileAndDirectory *fad; + + res = NULL; + for (l = files; l != NULL; l = l->next) { + fad = g_new0 (FileAndDirectory, 1); + fad->directory = nautilus_directory_ref (directory); + fad->file = nautilus_file_ref (l->data); + res = g_list_prepend (res, fad); + } + return g_list_reverse (res); +} + +static void +file_and_directory_free (FileAndDirectory *fad) +{ + nautilus_directory_unref (fad->directory); + nautilus_file_unref (fad->file); + g_free (fad); +} + + +static void +file_and_directory_list_free (GList *list) +{ + GList *l; + + for (l = list; l != NULL; l = l->next) { + file_and_directory_free (l->data); + } + + g_list_free (list); +} + +static gboolean +file_and_directory_equal (gconstpointer v1, + gconstpointer v2) +{ + const FileAndDirectory *fad1, *fad2; + fad1 = v1; + fad2 = v2; + + return (fad1->file == fad2->file && + fad1->directory == fad2->directory); +} + +static guint +file_and_directory_hash (gconstpointer v) +{ + const FileAndDirectory *fad; + + fad = v; + return GPOINTER_TO_UINT (fad->file) ^ GPOINTER_TO_UINT (fad->directory); +} + +static ScriptLaunchParameters * +script_launch_parameters_new (NautilusFile *file, + NautilusFilesView *directory_view) +{ + ScriptLaunchParameters *result; + + result = g_new0 (ScriptLaunchParameters, 1); + g_object_ref (directory_view); + result->directory_view = directory_view; + nautilus_file_ref (file); + result->file = file; + + return result; +} + +static void +script_launch_parameters_free (ScriptLaunchParameters *parameters) +{ + g_object_unref (parameters->directory_view); + nautilus_file_unref (parameters->file); + g_free (parameters); +} + +static CreateTemplateParameters * +create_template_parameters_new (NautilusFile *file, + NautilusFilesView *directory_view) +{ + CreateTemplateParameters *result; + + result = g_new0 (CreateTemplateParameters, 1); + g_object_ref (directory_view); + result->directory_view = directory_view; + nautilus_file_ref (file); + result->file = file; + + return result; +} + +static void +create_templates_parameters_free (CreateTemplateParameters *parameters) +{ + g_object_unref (parameters->directory_view); + nautilus_file_unref (parameters->file); + g_free (parameters); +} + +NautilusWindow * +nautilus_files_view_get_window (NautilusFilesView *view) +{ + return nautilus_window_slot_get_window (view->details->slot); +} + +NautilusWindowSlot * +nautilus_files_view_get_nautilus_window_slot (NautilusFilesView *view) +{ + g_assert (view->details->slot != NULL); + + return view->details->slot; +} + +/* Returns the GtkWindow that this directory view occupies, or NULL + * if at the moment this directory view is not in a GtkWindow or the + * GtkWindow cannot be determined. Primarily used for parenting dialogs. + */ +static GtkWindow * +nautilus_files_view_get_containing_window (NautilusFilesView *view) +{ + GtkWidget *window; + + g_assert (NAUTILUS_IS_FILES_VIEW (view)); + + window = gtk_widget_get_ancestor (GTK_WIDGET (view), GTK_TYPE_WINDOW); + if (window == NULL) { + return NULL; + } + + return GTK_WINDOW (window); +} + +static gboolean +nautilus_files_view_confirm_multiple (GtkWindow *parent_window, + int count, + gboolean tabs) +{ + GtkDialog *dialog; + char *prompt; + char *detail; + int response; + + if (count <= SILENT_WINDOW_OPEN_LIMIT) { + return TRUE; + } + + prompt = _("Are you sure you want to open all files?"); + if (tabs) { + detail = g_strdup_printf (ngettext("This will open %'d separate tab.", + "This will open %'d separate tabs.", count), count); + } else { + detail = g_strdup_printf (ngettext("This will open %'d separate window.", + "This will open %'d separate windows.", count), count); + } + dialog = eel_show_yes_no_dialog (prompt, detail, + _("_OK"), _("_Cancel"), + parent_window); + g_free (detail); + + response = gtk_dialog_run (dialog); + gtk_widget_destroy (GTK_WIDGET (dialog)); + + return response == GTK_RESPONSE_YES; +} + +static gboolean +selection_not_empty_in_menu_callback (NautilusFilesView *view, + GList *selection) +{ + if (selection != NULL) { + return TRUE; + } + + return FALSE; +} + +static char * +get_view_directory (NautilusFilesView *view) +{ + char *uri, *path; + GFile *f; + + uri = nautilus_directory_get_uri (view->details->model); + if (eel_uri_is_desktop (uri)) { + g_free (uri); + uri = nautilus_get_desktop_directory_uri (); + + } + f = g_file_new_for_uri (uri); + path = g_file_get_path (f); + g_object_unref (f); + g_free (uri); + + return path; +} + +void +nautilus_files_view_preview_files (NautilusFilesView *view, + GList *files, + GArray *locations) +{ + gchar *uri; + guint xid; + GtkWidget *toplevel; + + uri = nautilus_file_get_uri (files->data); + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (view)); + + xid = gdk_x11_window_get_xid (gtk_widget_get_window (toplevel)); + nautilus_previewer_call_show_file (uri, xid, TRUE); + + g_free (uri); +} + +void +nautilus_files_view_activate_selection (NautilusFilesView *view) +{ + GList *selection; + + selection = nautilus_files_view_get_selection (view); + nautilus_files_view_activate_files (view, + selection, + 0, + TRUE); + nautilus_file_list_free (selection); +} + +void +nautilus_files_view_activate_files (NautilusFilesView *view, + GList *files, + NautilusWindowOpenFlags flags, + gboolean confirm_multiple) +{ + char *path; + + path = get_view_directory (view); + nautilus_mime_activate_files (nautilus_files_view_get_containing_window (view), + view->details->slot, + files, + path, + flags, + confirm_multiple); + + g_free (path); +} + +static void +nautilus_files_view_activate_file (NautilusFilesView *view, + NautilusFile *file, + NautilusWindowOpenFlags flags) +{ + char *path; + + path = get_view_directory (view); + nautilus_mime_activate_file (nautilus_files_view_get_containing_window (view), + view->details->slot, + file, + path, + flags); + + g_free (path); +} + +static void +action_open_with_default_application (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusFilesView *view; + + view = NAUTILUS_FILES_VIEW (user_data); + nautilus_files_view_activate_selection (view); +} +static void +action_open_file_and_close_window (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + GList *selection; + NautilusFilesView *view; + + view = NAUTILUS_FILES_VIEW (user_data); + + selection = nautilus_files_view_get_selection (view); + nautilus_files_view_activate_files (view, + selection, + NAUTILUS_WINDOW_OPEN_FLAG_CLOSE_BEHIND, + TRUE); + nautilus_file_list_free (selection); +} + +static void +got_it_clicked (GtkDialog *dialog, + gint response_id, + gpointer user_data) +{ + g_settings_set_boolean (nautilus_preferences, + NAUTILUS_PREFERENCES_SHOW_MOVE_TO_TRASH_SHORTCUT_CHANGED_DIALOG, + FALSE); +} + +static void +action_show_move_to_trash_shortcut_changed_dialog (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusFilesView *view; + GtkWindow *dialog; + GtkBuilder *builder; + gboolean show_dialog_preference; + + view = NAUTILUS_FILES_VIEW (user_data); + show_dialog_preference = g_settings_get_boolean (nautilus_preferences, + NAUTILUS_PREFERENCES_SHOW_MOVE_TO_TRASH_SHORTCUT_CHANGED_DIALOG); + if (show_dialog_preference) { + builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/nautilus-move-to-trash-shortcut-changed.ui"); + dialog = GTK_WINDOW (gtk_builder_get_object (builder, "move_to_trash_shortcut_changed_dialog")); + + gtk_window_set_transient_for (dialog, GTK_WINDOW (nautilus_files_view_get_window (view))); + g_signal_connect (dialog, "response", + G_CALLBACK (got_it_clicked), + view); + + gtk_widget_show (GTK_WIDGET (dialog)); + gtk_dialog_run(GTK_DIALOG (dialog)); + gtk_widget_destroy (GTK_WIDGET (dialog)); + + g_object_unref (builder); + } +} +static void +action_open_item_location (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusFilesView *view; + GList *selection; + NautilusFile *item; + GFile *activation_location; + NautilusFile *activation_file; + NautilusFile *location; + + view = NAUTILUS_FILES_VIEW (user_data); + selection = nautilus_files_view_get_selection (view); + + if (!selection) + return; + + item = NAUTILUS_FILE (selection->data); + activation_location = nautilus_file_get_activation_location (item); + activation_file = nautilus_file_get (activation_location); + location = nautilus_file_get_parent (activation_file); + + nautilus_files_view_activate_file (view, location, 0); + + nautilus_file_unref (location); + nautilus_file_unref (activation_file); + g_object_unref (activation_location); + nautilus_file_list_free (selection); +} + +static void +action_open_item_new_tab (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusFilesView *view; + GList *selection; + GtkWindow *window; + + view = NAUTILUS_FILES_VIEW (user_data); + selection = nautilus_files_view_get_selection (view); + + window = nautilus_files_view_get_containing_window (view); + + if (nautilus_files_view_confirm_multiple (window, g_list_length (selection), TRUE)) { + nautilus_files_view_activate_files (view, + selection, + NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB, + FALSE); + } + + nautilus_file_list_free (selection); +} + +static void +app_chooser_dialog_response_cb (GtkDialog *dialog, + gint response_id, + gpointer user_data) +{ + GtkWindow *parent_window; + GList *files; + GAppInfo *info; + + parent_window = user_data; + files = g_object_get_data (G_OBJECT (dialog), "directory-view:files"); + + if (response_id != GTK_RESPONSE_OK) + goto out; + + info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (dialog)); + + g_signal_emit_by_name (nautilus_signaller_get_current (), "mime-data-changed"); + + nautilus_launch_application (info, files, parent_window); + + g_object_unref (info); +out: + gtk_widget_destroy (GTK_WIDGET (dialog)); +} + +static void +choose_program (NautilusFilesView *view, + GList *files) +{ + GtkWidget *dialog; + gchar *mime_type; + GtkWindow *parent_window; + + g_assert (NAUTILUS_IS_FILES_VIEW (view)); + + mime_type = nautilus_file_get_mime_type (files->data); + parent_window = nautilus_files_view_get_containing_window (view); + + dialog = gtk_app_chooser_dialog_new_for_content_type (parent_window, + GTK_DIALOG_MODAL | + GTK_DIALOG_DESTROY_WITH_PARENT | + GTK_DIALOG_USE_HEADER_BAR, + mime_type); + g_object_set_data_full (G_OBJECT (dialog), + "directory-view:files", + files, + (GDestroyNotify) nautilus_file_list_free); + gtk_widget_show (dialog); + + g_signal_connect_object (dialog, "response", + G_CALLBACK (app_chooser_dialog_response_cb), + parent_window, 0); +} + +static void +open_with_other_program (NautilusFilesView *view) +{ + GList *selection; + + g_assert (NAUTILUS_IS_FILES_VIEW (view)); + + selection = nautilus_files_view_get_selection (view); + choose_program (view, selection); +} + +static void +action_open_with_other_application (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + g_assert (NAUTILUS_IS_FILES_VIEW (user_data)); + + open_with_other_program (NAUTILUS_FILES_VIEW (user_data)); +} + +static void +trash_or_delete_selected_files (NautilusFilesView *view) +{ + GList *selection; + + /* This might be rapidly called multiple times for the same selection + * when using keybindings. So we remember if the current selection + * was already removed (but the view doesn't know about it yet). + */ + if (!view->details->selection_was_removed) { + selection = nautilus_files_view_get_selection_for_file_transfer (view); + trash_or_delete_files (nautilus_files_view_get_containing_window (view), + selection, + view); + nautilus_file_list_free (selection); + view->details->selection_was_removed = TRUE; + } +} + +static void +action_move_to_trash (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + trash_or_delete_selected_files (NAUTILUS_FILES_VIEW (user_data)); +} + +static void +action_remove_from_recent (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + /* TODO:implement a set of functions for this, is very confusing to + * call trash_or_delete_file to remove from recent, even if it does like + * that not deleting/moving the files to trash */ + trash_or_delete_selected_files (NAUTILUS_FILES_VIEW (user_data)); +} + +static void +delete_selected_files (NautilusFilesView *view) +{ + GList *selection; + GList *node; + GList *locations; + + selection = nautilus_files_view_get_selection_for_file_transfer (view); + if (selection == NULL) { + return; + } + + locations = NULL; + for (node = selection; node != NULL; node = node->next) { + locations = g_list_prepend (locations, + nautilus_file_get_location ((NautilusFile *) node->data)); + } + locations = g_list_reverse (locations); + + nautilus_file_operations_delete (locations, nautilus_files_view_get_containing_window (view), NULL, NULL); + + g_list_free_full (locations, g_object_unref); + nautilus_file_list_free (selection); +} + +static void +action_delete (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + delete_selected_files (NAUTILUS_FILES_VIEW (user_data)); +} + +static void +action_restore_from_trash (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusFilesView *view; + GList *selection; + + view = NAUTILUS_FILES_VIEW (user_data); + + selection = nautilus_files_view_get_selection_for_file_transfer (view); + nautilus_restore_files_from_trash (selection, + nautilus_files_view_get_containing_window (view)); + + nautilus_file_list_free (selection); + +} + +static void +action_select_all (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusFilesView *view; + + g_assert (NAUTILUS_IS_FILES_VIEW (user_data)); + + view = NAUTILUS_FILES_VIEW (user_data); + + nautilus_files_view_select_all (view); +} + +static void +action_invert_selection (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + g_assert (NAUTILUS_IS_FILES_VIEW (user_data)); + + nautilus_files_view_invert_selection (user_data); +} + +static void +pattern_select_response_cb (GtkWidget *dialog, + int response, + gpointer user_data) +{ + NautilusFilesView *view; + NautilusDirectory *directory; + GtkWidget *entry; + GList *selection; + + view = NAUTILUS_FILES_VIEW (user_data); + + switch (response) { + case GTK_RESPONSE_OK : + entry = g_object_get_data (G_OBJECT (dialog), "entry"); + directory = nautilus_files_view_get_model (view); + selection = nautilus_directory_match_pattern (directory, + gtk_entry_get_text (GTK_ENTRY (entry))); + + if (selection) { + nautilus_files_view_call_set_selection (view, selection); + nautilus_file_list_free (selection); + + nautilus_files_view_reveal_selection(view); + } + /* fall through */ + case GTK_RESPONSE_NONE : + case GTK_RESPONSE_DELETE_EVENT : + case GTK_RESPONSE_CANCEL : + gtk_widget_destroy (GTK_WIDGET (dialog)); + break; + default : + g_assert_not_reached (); + } +} + +static void +select_pattern (NautilusFilesView *view) +{ + GtkWidget *dialog; + GtkWidget *label; + GtkWidget *example; + GtkWidget *grid; + GtkWidget *entry; + char *example_pattern; + + dialog = gtk_dialog_new_with_buttons (_("Select Items Matching"), + nautilus_files_view_get_containing_window (view), + GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_USE_HEADER_BAR, + _("_Cancel"), + GTK_RESPONSE_CANCEL, + _("_Select"), + GTK_RESPONSE_OK, + NULL); + gtk_dialog_set_default_response (GTK_DIALOG (dialog), + GTK_RESPONSE_OK); + gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); + gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 2); + + label = gtk_label_new_with_mnemonic (_("_Pattern:")); + gtk_widget_set_halign (label, GTK_ALIGN_START); + + example = gtk_label_new (NULL); + gtk_widget_set_halign (example, GTK_ALIGN_START); + example_pattern = g_strdup_printf ("%s<i>%s</i> ", + _("Examples: "), + "*.png, file\?\?.txt, pict*.\?\?\?"); + gtk_label_set_markup (GTK_LABEL (example), example_pattern); + g_free (example_pattern); + + entry = gtk_entry_new (); + gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE); + gtk_widget_set_hexpand (entry, TRUE); + + grid = gtk_grid_new (); + g_object_set (grid, + "orientation", GTK_ORIENTATION_VERTICAL, + "border-width", 6, + "row-spacing", 6, + "column-spacing", 12, + NULL); + + gtk_container_add (GTK_CONTAINER (grid), label); + gtk_grid_attach_next_to (GTK_GRID (grid), entry, label, + GTK_POS_RIGHT, 1, 1); + gtk_grid_attach_next_to (GTK_GRID (grid), example, entry, + GTK_POS_BOTTOM, 1, 1); + + gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry); + gtk_widget_show_all (grid); + gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), grid); + g_object_set_data (G_OBJECT (dialog), "entry", entry); + g_signal_connect (dialog, "response", + G_CALLBACK (pattern_select_response_cb), + view); + gtk_widget_show_all (dialog); +} + +static void +action_select_pattern (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + g_assert (NAUTILUS_IS_FILES_VIEW (user_data)); + + select_pattern(user_data); +} + +static void +zoom_level_changed (GtkRange *range, + NautilusFilesView *view) +{ + g_action_group_change_action_state (view->details->view_action_group, + "zoom-to-level", + g_variant_new_int32 (gtk_range_get_value (range))); +} + +static void +reveal_newly_added_folder (NautilusFilesView *view, + NautilusFile *new_file, + NautilusDirectory *directory, + GFile *target_location) +{ + GFile *location; + + location = nautilus_file_get_location (new_file); + if (g_file_equal (location, target_location)) { + g_signal_handlers_disconnect_by_func (view, + G_CALLBACK (reveal_newly_added_folder), + (void *) target_location); + nautilus_files_view_select_file (view, new_file); + } + g_object_unref (location); +} + +typedef struct { + NautilusFilesView *directory_view; + GHashTable *added_locations; + GList *selection; +} NewFolderData; + +typedef struct { + NautilusFilesView *directory_view; + GHashTable *to_remove_locations; + NautilusFile *new_folder; +} NewFolderSelectionData; + +static void +track_newly_added_locations (NautilusFilesView *view, + NautilusFile *new_file, + NautilusDirectory *directory, + gpointer user_data) +{ + NewFolderData *data; + + data = user_data; + + g_hash_table_insert (data->added_locations, nautilus_file_get_location (new_file), NULL); +} + +static void +new_folder_done (GFile *new_folder, + gboolean success, + gpointer user_data) +{ + NautilusFilesView *directory_view; + NautilusFile *file; + char screen_string[32]; + GdkScreen *screen; + NewFolderData *data; + + data = (NewFolderData *)user_data; + + directory_view = data->directory_view; + + if (directory_view == NULL) { + goto fail; + } + + g_signal_handlers_disconnect_by_func (directory_view, + G_CALLBACK (track_newly_added_locations), + (void *) data); + + if (new_folder == NULL) { + goto fail; + } + + screen = gtk_widget_get_screen (GTK_WIDGET (directory_view)); + g_snprintf (screen_string, sizeof (screen_string), "%d", gdk_screen_get_number (screen)); + + + file = nautilus_file_get (new_folder); + nautilus_file_set_metadata + (file, NAUTILUS_METADATA_KEY_SCREEN, + NULL, + screen_string); + + if (data->selection != NULL) { + NewFolderSelectionData *sdata; + GList *uris, *l; + char *target_uri; + + sdata = g_new (NewFolderSelectionData, 1); + sdata->directory_view = directory_view; + sdata->to_remove_locations = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, + g_object_unref, NULL); + sdata->new_folder = g_object_ref (file); + + uris = NULL; + for (l = data->selection; l != NULL; l = l->next) { + GFile *old_location; + GFile *new_location; + char *basename; + + uris = g_list_prepend (uris, nautilus_file_get_uri ((NautilusFile *) l->data)); + + old_location = nautilus_file_get_location (l->data); + basename = g_file_get_basename (old_location); + new_location = g_file_resolve_relative_path (new_folder, basename); + g_hash_table_insert (sdata->to_remove_locations, new_location, NULL); + g_free (basename); + g_object_unref (old_location); + } + uris = g_list_reverse (uris); + + target_uri = nautilus_file_get_uri (file); + + nautilus_files_view_move_copy_items (directory_view, + uris, + NULL, + target_uri, + GDK_ACTION_MOVE, + 0, 0); + g_list_free_full (uris, g_free); + g_free (target_uri); + } else { + if (g_hash_table_lookup_extended (data->added_locations, new_folder, NULL, NULL)) { + /* The file was already added */ + nautilus_files_view_select_file (directory_view, file); + } else { + /* We need to run after the default handler adds the folder we want to + * operate on. The ADD_FILE signal is registered as G_SIGNAL_RUN_LAST, so we + * must use connect_after. + */ + g_signal_connect_data (directory_view, + "add-file", + G_CALLBACK (reveal_newly_added_folder), + g_object_ref (new_folder), + (GClosureNotify)g_object_unref, + G_CONNECT_AFTER); + } + } + + nautilus_file_unref (file); + + fail: + g_hash_table_destroy (data->added_locations); + + if (data->directory_view != NULL) { + g_object_remove_weak_pointer (G_OBJECT (data->directory_view), + (gpointer *) &data->directory_view); + } + + nautilus_file_list_free (data->selection); + g_free (data); +} + + +static NewFolderData * +new_folder_data_new (NautilusFilesView *directory_view, + gboolean with_selection) +{ + NewFolderData *data; + + data = g_new (NewFolderData, 1); + data->directory_view = directory_view; + data->added_locations = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, + g_object_unref, NULL); + if (with_selection) { + data->selection = nautilus_files_view_get_selection_for_file_transfer (directory_view); + } else { + data->selection = NULL; + } + g_object_add_weak_pointer (G_OBJECT (data->directory_view), + (gpointer *) &data->directory_view); + + return data; +} + +static GdkPoint * +context_menu_to_file_operation_position (NautilusFilesView *view) +{ + g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), NULL); + + if (nautilus_files_view_using_manual_layout (view) + && view->details->context_menu_position.x >= 0 + && view->details->context_menu_position.y >= 0) { + NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->widget_to_file_operation_position + (view, &view->details->context_menu_position); + return &view->details->context_menu_position; + } else { + return NULL; + } +} + +typedef struct { + NautilusFilesView *view; + GtkWidget *widget; + GtkWidget *error_label; + GtkWidget *name_entry; + GtkWidget *activate_button; + gboolean target_is_folder; + NautilusFile *target_file; + gboolean duplicated_is_folder; + void (*on_name_accepted) (gpointer data); + /* For create folder only */ + gboolean with_selection; +} FileNameWidgetData; + +static gboolean +duplicated_file_label_show (FileNameWidgetData *data) +{ + if (data->duplicated_is_folder) + gtk_label_set_label (GTK_LABEL (data->error_label), _("A folder with that name already exists.")); + else + gtk_label_set_label (GTK_LABEL (data->error_label), _("A file with that name already exists.")); + + data->view->details->duplicated_label_timeout_id = 0; + + return G_SOURCE_REMOVE; +} + +static gchar* +validate_file_name (const gchar *name, + gboolean is_folder) +{ + gchar *error_message = NULL; + + if (strstr (name, "/") != NULL) { + if (is_folder) + error_message = _("Folder names cannot contain “/”."); + else + error_message = _("Files names cannot contain “/”."); + } else if (strcmp (name, ".") == 0){ + if (is_folder) + error_message = _("A folder can not be called “.”."); + else + error_message = _("A file can not be called “.”."); + } else if (strcmp (name, "..") == 0){ + if (is_folder) + error_message = _("A folder can not be called “..”."); + else + error_message = _("A file can not be called “..”."); + } + + return error_message; +} + +static void +file_name_widget_entry_on_changed (gpointer user_data) +{ + FileNameWidgetData *data; + NautilusFile *existing_file; + gchar *name; + gchar *error_message; + gboolean valid_name; + gboolean duplicated; + + data = (FileNameWidgetData *) user_data; + name = g_strstrip (g_strdup (gtk_entry_get_text (GTK_ENTRY (data->name_entry)))); + error_message = validate_file_name (name, TRUE); + gtk_label_set_label (GTK_LABEL (data->error_label), error_message); + + existing_file = nautilus_directory_get_file_by_name (data->view->details->model, name); + + valid_name = strlen (name) > 0 && error_message == NULL; + /* If there is a target file and the name is the same, we don't show it + * as duplicated. This is the case for renaming. */ + duplicated = existing_file != NULL && + (data->target_file == NULL || + nautilus_file_compare_display_name (data->target_file, name) != 0); + gtk_widget_set_sensitive (data->activate_button, valid_name && !duplicated); + + if (data->view->details->duplicated_label_timeout_id > 0) { + g_source_remove (data->view->details->duplicated_label_timeout_id); + data->view->details->duplicated_label_timeout_id = 0; + } + + /* Report duplicated file only if not other message shown (for instance, + * folders like "." or ".." will always exists, but we consider it as an + * error, not as a duplicated file or if the name is the same as the file + * we are renaming also don't report as a duplicated */ + if (duplicated && valid_name) { + data->duplicated_is_folder = nautilus_file_is_directory (existing_file); + data->view->details->duplicated_label_timeout_id = + g_timeout_add (FILE_NAME_DUPLICATED_LABEL_TIMEOUT, + (GSourceFunc)duplicated_file_label_show, + data); + } + + if (existing_file != NULL) + nautilus_file_unref (existing_file); + + g_free (name); +} + +static void +create_folder_dialog_on_response (GtkDialog *dialog, + gint response_id, + gpointer user_data) +{ + FileNameWidgetData *widget_data; + + widget_data = (FileNameWidgetData *) user_data; + + if (response_id == GTK_RESPONSE_OK) { + NewFolderData *data; + GdkPoint *pos; + char *parent_uri; + gchar *name; + + data = new_folder_data_new (widget_data->view, widget_data->with_selection); + + name = g_strstrip (g_strdup (gtk_entry_get_text (GTK_ENTRY (widget_data->name_entry)))); + g_signal_connect_data (widget_data->view, + "add-file", + G_CALLBACK (track_newly_added_locations), + data, + (GClosureNotify)NULL, + G_CONNECT_AFTER); + + pos = context_menu_to_file_operation_position (widget_data->view); + + parent_uri = nautilus_files_view_get_backing_uri (widget_data->view); + nautilus_file_operations_new_folder (GTK_WIDGET (widget_data->view), + pos, parent_uri, name, + new_folder_done, data); + + g_free (parent_uri); + g_free (name); + } + + gtk_widget_destroy (GTK_WIDGET (dialog)); + g_free (user_data); +} + + +static void +create_folder_on_name_accepted (gpointer user_data) +{ + FileNameWidgetData *data; + + data = (FileNameWidgetData *) user_data; + gtk_dialog_response (GTK_DIALOG (data->widget), + GTK_RESPONSE_OK); +} + +static void +rename_file_on_name_accepted (gpointer user_data) +{ + FileNameWidgetData *data; + gchar *name; + + data = (FileNameWidgetData *) user_data; + + name = g_strstrip (g_strdup (gtk_entry_get_text (GTK_ENTRY (data->name_entry)))); + nautilus_rename_file (data->target_file, name, NULL, NULL); + + nautilus_files_view_select_file (data->view, data->target_file); + nautilus_files_view_reveal_selection (data->view); + + gtk_widget_hide (data->widget); + + g_free (name); +} + +static void +file_name_widget_on_activate (gpointer user_data) +{ + FileNameWidgetData *data; + NautilusFile *existing_file; + gchar *name; + gchar *error_message; + gboolean valid_name; + gboolean duplicated; + + data = (FileNameWidgetData *) user_data; + name = g_strstrip (g_strdup (gtk_entry_get_text (GTK_ENTRY (data->name_entry)))); + existing_file = nautilus_directory_get_file_by_name (data->view->details->model, name); + error_message = validate_file_name (name, TRUE); + valid_name = strlen (name) > 0 && error_message == NULL; + duplicated = existing_file != NULL && + (data->target_file == NULL || + nautilus_file_compare_display_name (data->target_file, name) != 0); + + if (data->view->details->duplicated_label_timeout_id > 0) { + g_source_remove (data->view->details->duplicated_label_timeout_id); + data->view->details->duplicated_label_timeout_id = 0; + } + + if (valid_name && !duplicated) { + data->on_name_accepted ((gpointer) data); + } else { + /* Report duplicated file only if not other message shown (for instance, + * folders like "." or ".." will always exists, but we consider it as an + * error, not as a duplicated file) */ + if (existing_file != NULL && valid_name) { + data->duplicated_is_folder = nautilus_file_is_directory (existing_file); + /* Show it inmediatily since the user tried to trigger the action */ + duplicated_file_label_show (data); + } + } + + if (existing_file != NULL) + nautilus_file_unref (existing_file); + +} + +static void +rename_file_popover_on_closed (GtkPopover *popover, + gpointer user_data) +{ + FileNameWidgetData *widget_data; + + widget_data = (FileNameWidgetData *) user_data; + widget_data->view->details->rename_file_popover = NULL; + g_free (widget_data); +} + +static GdkRectangle* +nautilus_files_view_compute_rename_popover_relative_to (NautilusFilesView *view) +{ + return NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->compute_rename_popover_relative_to (view); +} + +static void +nautilus_files_view_rename_file_popover_new (NautilusFilesView *view, + NautilusFile *target_file) +{ + FileNameWidgetData *widget_data; + GtkWidget *label_file_name; + GtkBuilder *builder; + gint start_offset, end_offset; + GdkRectangle *relative_to; + + if (view->details->rename_file_popover != NULL) + return; + + builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/nautilus-rename-file-popover.ui"); + label_file_name = GTK_WIDGET (gtk_builder_get_object (builder, "name_label")); + + widget_data = g_new (FileNameWidgetData, 1); + widget_data->view = view; + widget_data->on_name_accepted = rename_file_on_name_accepted; + widget_data->widget = GTK_WIDGET (gtk_builder_get_object (builder, "rename_file_popover")); + widget_data->activate_button = GTK_WIDGET (gtk_builder_get_object (builder, "rename_button")); + widget_data->error_label = GTK_WIDGET (gtk_builder_get_object (builder, "error_label")); + widget_data->name_entry = GTK_WIDGET (gtk_builder_get_object (builder, "name_entry")); + widget_data->target_is_folder = nautilus_file_is_directory (target_file); + widget_data->target_file = target_file; + + view->details->rename_file_popover = widget_data->widget; + + /* Connect signals */ + gtk_builder_add_callback_symbols (builder, + "file_name_widget_entry_on_changed", + G_CALLBACK (file_name_widget_entry_on_changed), + "file_name_widget_on_activate", + G_CALLBACK (file_name_widget_on_activate), + "rename_file_popover_on_closed", + G_CALLBACK (rename_file_popover_on_closed), + "rename_file_popover_on_unmap", + G_CALLBACK (gtk_widget_destroy), + NULL); + + gtk_builder_connect_signals (builder, widget_data); + + if (widget_data->target_is_folder) + gtk_label_set_text (GTK_LABEL (label_file_name), _("Folder name")); + else + gtk_label_set_text (GTK_LABEL (label_file_name), _("File name")); + gtk_entry_set_text (GTK_ENTRY (widget_data->name_entry), nautilus_file_get_name (target_file)); + + relative_to = nautilus_files_view_compute_rename_popover_relative_to (view); + gtk_popover_set_default_widget (GTK_POPOVER (widget_data->widget), + widget_data->activate_button); + gtk_popover_set_pointing_to (GTK_POPOVER (widget_data->widget), relative_to); + gtk_popover_set_relative_to (GTK_POPOVER (widget_data->widget), + GTK_WIDGET (view)); + gtk_widget_show (widget_data->widget); + gtk_widget_grab_focus (widget_data->widget); + + /* Select the name part withouth the file extension */ + eel_filename_get_rename_region (nautilus_file_get_name (target_file), + &start_offset, &end_offset); + gtk_editable_select_region (GTK_EDITABLE (widget_data->name_entry), + start_offset, end_offset); + + /* Update the rename button status */ + file_name_widget_entry_on_changed (widget_data); + + + g_object_unref (builder); +} + +static void +nautilus_files_view_new_folder_dialog_new (NautilusFilesView *view, + gboolean with_selection) +{ + FileNameWidgetData *widget_data; + GtkWidget *label_file_name; + GtkBuilder *builder; + + builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/nautilus-create-folder-dialog.ui"); + label_file_name = GTK_WIDGET (gtk_builder_get_object (builder, "name_label")); + + widget_data = g_new (FileNameWidgetData, 1); + widget_data->view = view; + widget_data->on_name_accepted = create_folder_on_name_accepted; + widget_data->widget = GTK_WIDGET (gtk_builder_get_object (builder, "create_folder_dialog")); + widget_data->activate_button = GTK_WIDGET (gtk_builder_get_object (builder, "ok_button")); + widget_data->error_label = GTK_WIDGET (gtk_builder_get_object (builder, "error_label")); + widget_data->name_entry = GTK_WIDGET (gtk_builder_get_object (builder, "name_entry")); + widget_data->target_is_folder = TRUE; + widget_data->target_file = NULL; + widget_data->with_selection = with_selection; + + gtk_window_set_transient_for (GTK_WINDOW (widget_data->widget), + GTK_WINDOW (nautilus_files_view_get_window (view))); + + /* Connect signals */ + gtk_builder_add_callback_symbols (builder, + "file_name_widget_entry_on_changed", + G_CALLBACK (file_name_widget_entry_on_changed), + "file_name_widget_on_activate", + G_CALLBACK (file_name_widget_on_activate), + "create_folder_dialog_on_response", + G_CALLBACK (create_folder_dialog_on_response), + NULL); + + gtk_builder_connect_signals (builder, widget_data); + gtk_button_set_label (GTK_BUTTON (widget_data->activate_button), + _("Create")); + gtk_label_set_text (GTK_LABEL (label_file_name), _("Folder name")); + gtk_window_set_title (GTK_WINDOW (widget_data->widget), _("New Folder")); + + gtk_widget_show_all (widget_data->widget); + /* Update the ok button status */ + file_name_widget_entry_on_changed (widget_data); + + g_object_unref (builder); +} + +static void +nautilus_files_view_new_folder (NautilusFilesView *directory_view, + gboolean with_selection) +{ + nautilus_files_view_new_folder_dialog_new (directory_view, with_selection); +} + +static NewFolderData * +setup_new_folder_data (NautilusFilesView *directory_view) +{ + NewFolderData *data; + + data = new_folder_data_new (directory_view, FALSE); + + g_signal_connect_data (directory_view, + "add-file", + G_CALLBACK (track_newly_added_locations), + data, + (GClosureNotify)NULL, + G_CONNECT_AFTER); + + return data; +} + +void +nautilus_files_view_new_file_with_initial_contents (NautilusFilesView *view, + const char *parent_uri, + const char *filename, + const char *initial_contents, + int length, + GdkPoint *pos) +{ + NewFolderData *data; + + g_assert (parent_uri != NULL); + + data = setup_new_folder_data (view); + + if (pos == NULL) { + pos = context_menu_to_file_operation_position (view); + } + + nautilus_file_operations_new_file (GTK_WIDGET (view), + pos, parent_uri, filename, + initial_contents, length, + new_folder_done, data); +} + +static void +nautilus_files_view_new_file (NautilusFilesView *directory_view, + const char *parent_uri, + NautilusFile *source) +{ + GdkPoint *pos; + NewFolderData *data; + char *source_uri; + char *container_uri; + + container_uri = NULL; + if (parent_uri == NULL) { + container_uri = nautilus_files_view_get_backing_uri (directory_view); + g_assert (container_uri != NULL); + } + + if (source == NULL) { + nautilus_files_view_new_file_with_initial_contents (directory_view, + parent_uri != NULL ? parent_uri : container_uri, + NULL, + NULL, + 0, + NULL); + g_free (container_uri); + return; + } + + g_return_if_fail (nautilus_file_is_local (source)); + + pos = context_menu_to_file_operation_position (directory_view); + + data = setup_new_folder_data (directory_view); + + source_uri = nautilus_file_get_uri (source); + + nautilus_file_operations_new_file_from_template (GTK_WIDGET (directory_view), + pos, + parent_uri != NULL ? parent_uri : container_uri, + NULL, + source_uri, + new_folder_done, data); + + g_free (source_uri); + g_free (container_uri); +} + +static void +action_new_folder (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + g_assert (NAUTILUS_IS_FILES_VIEW (user_data)); + + nautilus_files_view_new_folder (NAUTILUS_FILES_VIEW (user_data), FALSE); +} + +static void +action_new_folder_with_selection (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + g_assert (NAUTILUS_IS_FILES_VIEW (user_data)); + + nautilus_files_view_new_folder (NAUTILUS_FILES_VIEW (user_data), TRUE); +} + +static void +action_properties (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusFilesView *view; + GList *selection; + GList *files; + + g_assert (NAUTILUS_IS_FILES_VIEW (user_data)); + + view = NAUTILUS_FILES_VIEW (user_data); + selection = nautilus_files_view_get_selection (view); + if (g_list_length (selection) == 0) { + if (view->details->directory_as_file != NULL) { + files = g_list_append (NULL, nautilus_file_ref (view->details->directory_as_file)); + + nautilus_properties_window_present (files, GTK_WIDGET (view), NULL); + + nautilus_file_list_free (files); + } + } else { + nautilus_properties_window_present (selection, GTK_WIDGET (view), NULL); + } + nautilus_file_list_free (selection); +} + +static void +nautilus_files_view_set_show_hidden_files (NautilusFilesView *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; + + g_settings_set_boolean (gtk_filechooser_preferences, + NAUTILUS_PREFERENCES_SHOW_HIDDEN_FILES, + show_hidden); + + if (view->details->model != NULL) { + load_directory (view, view->details->model); + } + } +} + +static void +action_show_hidden_files (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + gboolean show_hidden; + NautilusFilesView *view; + + g_assert (NAUTILUS_IS_FILES_VIEW (user_data)); + + view = NAUTILUS_FILES_VIEW (user_data); + show_hidden = g_variant_get_boolean (state); + + nautilus_files_view_set_show_hidden_files (view, show_hidden); + + g_simple_action_set_state (action, state); +} + +static void +action_zoom_in (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusFilesView *view; + + g_assert (NAUTILUS_IS_FILES_VIEW (user_data)); + + view = NAUTILUS_FILES_VIEW (user_data); + + nautilus_files_view_bump_zoom_level (view, 1); +} + +static void +action_zoom_out (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusFilesView *view; + + g_assert (NAUTILUS_IS_FILES_VIEW (user_data)); + + view = NAUTILUS_FILES_VIEW (user_data); + + nautilus_files_view_bump_zoom_level (view, -1); +} + +static void +action_zoom_default (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + nautilus_files_view_restore_default_zoom_level (user_data); +} + +static void +action_open_item_new_window (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusFilesView *view; + GtkWindow *window; + GList *selection; + + view = NAUTILUS_FILES_VIEW (user_data); + selection = nautilus_files_view_get_selection (view); + window = GTK_WINDOW (nautilus_files_view_get_containing_window (view)); + + if (nautilus_files_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 +paste_clipboard_data (NautilusFilesView *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_files_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) +{ + NautilusFilesView *view; + char *view_uri; + + view = NAUTILUS_FILES_VIEW (data); + + view_uri = nautilus_files_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) +{ + NautilusFilesView *view; + + g_assert (NAUTILUS_IS_FILES_VIEW (user_data)); + + view = NAUTILUS_FILES_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 +click_policy_changed_callback (gpointer callback_data) +{ + NautilusFilesView *view; + + view = NAUTILUS_FILES_VIEW (callback_data); + + NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->click_policy_changed (view); +} + +gboolean +nautilus_files_view_should_sort_directories_first (NautilusFilesView *view) +{ + return view->details->sort_directories_first; +} + +static void +sort_directories_first_changed_callback (gpointer callback_data) +{ + NautilusFilesView *view; + gboolean preference_value; + + view = NAUTILUS_FILES_VIEW (callback_data); + + preference_value = + g_settings_get_boolean (nautilus_preferences, NAUTILUS_PREFERENCES_SORT_DIRECTORIES_FIRST); + + if (preference_value != view->details->sort_directories_first) { + view->details->sort_directories_first = preference_value; + NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->sort_directories_first_changed (view); + } +} + +static void +show_hidden_files_changed_callback (gpointer callback_data) +{ + NautilusFilesView *view; + gboolean preference_value; + + view = NAUTILUS_FILES_VIEW (callback_data); + + preference_value = + g_settings_get_boolean (gtk_filechooser_preferences, NAUTILUS_PREFERENCES_SHOW_HIDDEN_FILES); + + nautilus_files_view_set_show_hidden_files (view, preference_value); +} + +static gboolean +set_up_scripts_directory_global (void) +{ + char *old_scripts_directory_path; + char *scripts_directory_path; + const char *override; + + if (scripts_directory_uri != NULL) { + return TRUE; + } + + scripts_directory_path = nautilus_get_scripts_directory_path (); + + override = g_getenv ("GNOME22_USER_DIR"); + + if (override) { + old_scripts_directory_path = g_build_filename (override, + "nautilus-scripts", + NULL); + } else { + old_scripts_directory_path = g_build_filename (g_get_home_dir (), + ".gnome2", + "nautilus-scripts", + NULL); + } + + if (g_file_test (old_scripts_directory_path, G_FILE_TEST_IS_DIR) + && !g_file_test (scripts_directory_path, G_FILE_TEST_EXISTS)) { + char *updated; + const char *message; + + /* test if we already attempted to migrate first */ + updated = g_build_filename (old_scripts_directory_path, "DEPRECATED-DIRECTORY", NULL); + message = _("Nautilus 3.6 deprecated this directory and tried migrating " + "this configuration to ~/.local/share/nautilus"); + if (!g_file_test (updated, G_FILE_TEST_EXISTS)) { + char *parent_dir; + + parent_dir = g_path_get_dirname (scripts_directory_path); + if (g_mkdir_with_parents (parent_dir, 0700) == 0) { + int fd, res; + + /* rename() works fine if the destination directory is + * empty. + */ + res = g_rename (old_scripts_directory_path, scripts_directory_path); + if (res == -1) { + fd = g_creat (updated, 0600); + if (fd != -1) { + res = write (fd, message, strlen (message)); + close (fd); + } + } + } + g_free (parent_dir); + } + + g_free (updated); + } + + if (g_mkdir_with_parents (scripts_directory_path, 0700) == 0) { + scripts_directory_uri = g_filename_to_uri (scripts_directory_path, NULL, NULL); + scripts_directory_uri_length = strlen (scripts_directory_uri); + } + + g_free (scripts_directory_path); + g_free (old_scripts_directory_path); + + return (scripts_directory_uri != NULL) ? TRUE : FALSE; +} + +static void +scripts_added_or_changed_callback (NautilusDirectory *directory, + GList *files, + gpointer callback_data) +{ + NautilusFilesView *view; + + view = NAUTILUS_FILES_VIEW (callback_data); + + if (view->details->active) { + schedule_update_context_menus (view); + } +} + +static void +templates_added_or_changed_callback (NautilusDirectory *directory, + GList *files, + gpointer callback_data) +{ + NautilusFilesView *view; + + view = NAUTILUS_FILES_VIEW (callback_data); + + if (view->details->active) { + schedule_update_context_menus (view); + } +} + +static void +add_directory_to_directory_list (NautilusFilesView *view, + NautilusDirectory *directory, + GList **directory_list, + GCallback changed_callback) +{ + NautilusFileAttributes attributes; + + if (g_list_find (*directory_list, directory) == NULL) { + nautilus_directory_ref (directory); + + attributes = + NAUTILUS_FILE_ATTRIBUTES_FOR_ICON | + NAUTILUS_FILE_ATTRIBUTE_INFO | + NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT; + + nautilus_directory_file_monitor_add (directory, directory_list, + FALSE, attributes, + (NautilusDirectoryCallback)changed_callback, view); + + g_signal_connect_object (directory, "files-added", + G_CALLBACK (changed_callback), view, 0); + g_signal_connect_object (directory, "files-changed", + G_CALLBACK (changed_callback), view, 0); + + *directory_list = g_list_append (*directory_list, directory); + } +} + +static void +remove_directory_from_directory_list (NautilusFilesView *view, + NautilusDirectory *directory, + GList **directory_list, + GCallback changed_callback) +{ + *directory_list = g_list_remove (*directory_list, directory); + + g_signal_handlers_disconnect_by_func (directory, + G_CALLBACK (changed_callback), + view); + + nautilus_directory_file_monitor_remove (directory, directory_list); + + nautilus_directory_unref (directory); +} + + +static void +add_directory_to_scripts_directory_list (NautilusFilesView *view, + NautilusDirectory *directory) +{ + add_directory_to_directory_list (view, directory, + &view->details->scripts_directory_list, + G_CALLBACK (scripts_added_or_changed_callback)); +} + +static void +remove_directory_from_scripts_directory_list (NautilusFilesView *view, + NautilusDirectory *directory) +{ + remove_directory_from_directory_list (view, directory, + &view->details->scripts_directory_list, + G_CALLBACK (scripts_added_or_changed_callback)); +} + +static void +add_directory_to_templates_directory_list (NautilusFilesView *view, + NautilusDirectory *directory) +{ + add_directory_to_directory_list (view, directory, + &view->details->templates_directory_list, + G_CALLBACK (templates_added_or_changed_callback)); +} + +static void +remove_directory_from_templates_directory_list (NautilusFilesView *view, + NautilusDirectory *directory) +{ + remove_directory_from_directory_list (view, directory, + &view->details->templates_directory_list, + G_CALLBACK (templates_added_or_changed_callback)); +} + +static void +slot_active (NautilusWindowSlot *slot, + NautilusFilesView *view) +{ + if (view->details->active) { + return; + } + + view->details->active = TRUE; + + /* 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_files_view_update_context_menus(view); + nautilus_files_view_update_toolbar_menus (view); + + schedule_update_context_menus (view); + + gtk_widget_insert_action_group (GTK_WIDGET (nautilus_files_view_get_window (view)), + "view", + G_ACTION_GROUP (view->details->view_action_group)); +} + +static void +slot_inactive (NautilusWindowSlot *slot, + NautilusFilesView *view) +{ + if (!view->details->active) { + return; + } + + view->details->active = FALSE; + + remove_update_context_menus_timeout_callback (view); + gtk_widget_insert_action_group (GTK_WIDGET (nautilus_files_view_get_window (view)), + "view", + NULL); +} + +static void +nautilus_files_view_grab_focus (GtkWidget *widget) +{ + /* focus the child of the scrolled window if it exists */ + NautilusFilesView *view; + GtkWidget *child; + + view = NAUTILUS_FILES_VIEW (widget); + child = gtk_bin_get_child (GTK_BIN (view->details->scrolled_window)); + + GTK_WIDGET_CLASS (nautilus_files_view_parent_class)->grab_focus (widget); + + if (child) { + gtk_widget_grab_focus (GTK_WIDGET (child)); + } +} + +int +nautilus_files_view_get_selection_count (NautilusFilesView *view) +{ + /* FIXME: This could be faster if we special cased it in subclasses */ + GList *files; + int len; + + files = nautilus_files_view_get_selection (NAUTILUS_FILES_VIEW (view)); + len = g_list_length (files); + nautilus_file_list_free (files); + + return len; +} + +void +nautilus_files_view_set_selection (NautilusFilesView *nautilus_files_view, + GList *selection) +{ + NautilusFilesView *view; + + view = NAUTILUS_FILES_VIEW (nautilus_files_view); + + if (!view->details->loading) { + /* If we aren't still loading, set the selection right now, + * and reveal the new selection. + */ + nautilus_files_view_call_set_selection (view, selection); + nautilus_files_view_reveal_selection (view); + } else { + /* If we are still loading, set the list of pending URIs instead. + * done_loading() will eventually select the pending URIs and reveal them. + */ + g_list_free_full (view->details->pending_selection, g_object_unref); + view->details->pending_selection = + g_list_copy_deep (selection, (GCopyFunc) g_object_ref, NULL); + } +} + +static char * +get_bulk_rename_tool () +{ + char *bulk_rename_tool; + g_settings_get (nautilus_preferences, NAUTILUS_PREFERENCES_BULK_RENAME_TOOL, "^ay", &bulk_rename_tool); + return g_strstrip (bulk_rename_tool); +} + +static gboolean +have_bulk_rename_tool () +{ + char *bulk_rename_tool; + gboolean have_tool; + + bulk_rename_tool = get_bulk_rename_tool (); + have_tool = ((bulk_rename_tool != NULL) && (*bulk_rename_tool != '\0')); + g_free (bulk_rename_tool); + return have_tool; +} + +static void +nautilus_files_view_destroy (GtkWidget *object) +{ + NautilusFilesView *view; + GList *node, *next; + + view = NAUTILUS_FILES_VIEW (object); + + nautilus_files_view_stop_loading (view); + + for (node = view->details->scripts_directory_list; node != NULL; node = next) { + next = node->next; + remove_directory_from_scripts_directory_list (view, node->data); + } + + for (node = view->details->templates_directory_list; node != NULL; node = next) { + next = node->next; + remove_directory_from_templates_directory_list (view, node->data); + } + + while (view->details->subdirectory_list != NULL) { + nautilus_files_view_remove_subdirectory (view, + view->details->subdirectory_list->data); + } + + remove_update_context_menus_timeout_callback (view); + remove_update_status_idle_callback (view); + + if (view->details->display_selection_idle_id != 0) { + g_source_remove (view->details->display_selection_idle_id); + view->details->display_selection_idle_id = 0; + } + + if (view->details->reveal_selection_idle_id != 0) { + g_source_remove (view->details->reveal_selection_idle_id); + view->details->reveal_selection_idle_id = 0; + } + + if (view->details->floating_bar_set_status_timeout_id != 0) { + g_source_remove (view->details->floating_bar_set_status_timeout_id); + view->details->floating_bar_set_status_timeout_id = 0; + } + + if (view->details->floating_bar_loading_timeout_id != 0) { + g_source_remove (view->details->floating_bar_loading_timeout_id); + view->details->floating_bar_loading_timeout_id = 0; + } + + + if (view->details->directory_as_file) { + nautilus_file_unref (view->details->directory_as_file); + view->details->directory_as_file = NULL; + } + + /* We don't own the slot, so no unref */ + view->details->slot = NULL; + + GTK_WIDGET_CLASS (nautilus_files_view_parent_class)->destroy (object); +} + +static void +nautilus_files_view_finalize (GObject *object) +{ + NautilusFilesView *view; + + view = NAUTILUS_FILES_VIEW (object); + + g_signal_handlers_disconnect_by_func (nautilus_preferences, + 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, + sort_directories_first_changed_callback, view); + g_signal_handlers_disconnect_by_func (gtk_filechooser_preferences, + show_hidden_files_changed_callback, view); + g_signal_handlers_disconnect_by_func (nautilus_window_state, + nautilus_files_view_display_selection_info, view); + + g_signal_handlers_disconnect_by_func (gnome_lockdown_preferences, + schedule_update_context_menus, view); + + g_hash_table_destroy (view->details->non_ready_files); + + if (view->details->rename_file_popover != NULL) { + gtk_popover_set_relative_to (GTK_POPOVER (view->details->rename_file_popover), + NULL); + } + + G_OBJECT_CLASS (nautilus_files_view_parent_class)->finalize (object); +} + +/** + * nautilus_files_view_display_selection_info: + * + * Display information about the current selection, and notify the view frame of the changed selection. + * @view: NautilusFilesView for which to display selection info. + * + **/ +void +nautilus_files_view_display_selection_info (NautilusFilesView *view) +{ + GList *selection; + goffset non_folder_size; + gboolean non_folder_size_known; + guint non_folder_count, folder_count, folder_item_count; + gboolean folder_item_count_known; + guint file_item_count; + GList *p; + char *first_item_name; + char *non_folder_count_str; + char *non_folder_item_count_str; + char *folder_count_str; + char *folder_item_count_str; + char *primary_status; + char *detail_status; + NautilusFile *file; + + g_return_if_fail (NAUTILUS_IS_FILES_VIEW (view)); + + selection = nautilus_files_view_get_selection (view); + + folder_item_count_known = TRUE; + folder_count = 0; + folder_item_count = 0; + non_folder_count = 0; + non_folder_size_known = FALSE; + non_folder_size = 0; + first_item_name = NULL; + folder_count_str = NULL; + folder_item_count_str = NULL; + non_folder_count_str = NULL; + non_folder_item_count_str = NULL; + + for (p = selection; p != NULL; p = p->next) { + file = p->data; + if (nautilus_file_is_directory (file)) { + folder_count++; + if (nautilus_file_get_directory_item_count (file, &file_item_count, NULL)) { + folder_item_count += file_item_count; + } else { + folder_item_count_known = FALSE; + } + } else { + non_folder_count++; + if (!nautilus_file_can_get_size (file)) { + non_folder_size_known = TRUE; + non_folder_size += nautilus_file_get_size (file); + } + } + + if (first_item_name == NULL) { + first_item_name = nautilus_file_get_display_name (file); + } + } + + nautilus_file_list_free (selection); + + /* Break out cases for localization's sake. But note that there are still pieces + * being assembled in a particular order, which may be a problem for some localizers. + */ + + if (folder_count != 0) { + if (folder_count == 1 && non_folder_count == 0) { + folder_count_str = g_strdup_printf (_("“%s” selected"), first_item_name); + } else { + folder_count_str = g_strdup_printf (ngettext("%'d folder selected", + "%'d folders selected", + folder_count), + folder_count); + } + + if (folder_count == 1) { + if (!folder_item_count_known) { + folder_item_count_str = g_strdup (""); + } else { + folder_item_count_str = g_strdup_printf (ngettext("(containing %'d item)", + "(containing %'d items)", + folder_item_count), + folder_item_count); + } + } + else { + if (!folder_item_count_known) { + folder_item_count_str = g_strdup (""); + } else { + /* translators: this is preceded with a string of form 'N folders' (N more than 1) */ + folder_item_count_str = g_strdup_printf (ngettext("(containing a total of %'d item)", + "(containing a total of %'d items)", + folder_item_count), + folder_item_count); + } + + } + } + + if (non_folder_count != 0) { + if (folder_count == 0) { + if (non_folder_count == 1) { + non_folder_count_str = g_strdup_printf (_("“%s” selected"), + first_item_name); + } else { + non_folder_count_str = g_strdup_printf (ngettext("%'d item selected", + "%'d items selected", + non_folder_count), + non_folder_count); + } + } else { + /* Folders selected also, use "other" terminology */ + non_folder_count_str = g_strdup_printf (ngettext("%'d other item selected", + "%'d other items selected", + non_folder_count), + non_folder_count); + } + + if (non_folder_size_known) { + char *size_string; + + size_string = g_format_size (non_folder_size); + /* This is marked for translation in case a localiser + * needs to use something other than parentheses. The + * the message in parentheses is the size of the selected items. + */ + non_folder_item_count_str = g_strdup_printf (_("(%s)"), size_string); + g_free (size_string); + } else { + non_folder_item_count_str = g_strdup (""); + } + } + + if (folder_count == 0 && non_folder_count == 0) { + primary_status = NULL; + detail_status = NULL; + } else if (folder_count == 0) { + primary_status = g_strdup (non_folder_count_str); + detail_status = g_strdup (non_folder_item_count_str); + } else if (non_folder_count == 0) { + primary_status = g_strdup (folder_count_str); + detail_status = g_strdup (folder_item_count_str); + } else { + /* This is marked for translation in case a localizer + * needs to change ", " to something else. The comma + * is between the message about the number of folders + * and the number of items in those folders and the + * message about the number of other items and the + * total size of those items. + */ + primary_status = g_strdup_printf (_("%s %s, %s %s"), + folder_count_str, + folder_item_count_str, + non_folder_count_str, + non_folder_item_count_str); + detail_status = NULL; + } + + g_free (first_item_name); + g_free (folder_count_str); + g_free (folder_item_count_str); + g_free (non_folder_count_str); + g_free (non_folder_item_count_str); + + set_floating_bar_status (view, primary_status, detail_status); + + g_free (primary_status); + g_free (detail_status); +} + +static void +nautilus_files_view_send_selection_change (NautilusFilesView *view) +{ + g_signal_emit (view, signals[SELECTION_CHANGED], 0); +} + +void +nautilus_files_view_load_location (NautilusFilesView *nautilus_files_view, + GFile *location) +{ + NautilusDirectory *directory; + + nautilus_profile_start (NULL); + directory = nautilus_directory_get (location); + load_directory (nautilus_files_view, directory); + nautilus_directory_unref (directory); + nautilus_profile_end (NULL); +} + +static gboolean +reveal_selection_idle_callback (gpointer data) +{ + NautilusFilesView *view; + + view = NAUTILUS_FILES_VIEW (data); + + view->details->reveal_selection_idle_id = 0; + nautilus_files_view_reveal_selection (view); + + return FALSE; +} + +static void +done_loading (NautilusFilesView *view, + gboolean all_files_seen) +{ + GList *selection; + gboolean do_reveal = FALSE; + + if (!view->details->loading) { + return; + } + + nautilus_profile_start (NULL); + + /* This can be called during destruction, in which case we set the model + * as NULL. */ + if (view->details->model != NULL) { + nautilus_files_view_update_toolbar_menus (view); + remove_loading_floating_bar (view); + schedule_update_context_menus (view); + schedule_update_status (view); + reset_update_interval (view); + + selection = view->details->pending_selection; + + if (nautilus_files_view_is_search (view) && all_files_seen) { + nautilus_files_view_select_first (view); + do_reveal = TRUE; + } else if (selection != NULL && all_files_seen) { + view->details->pending_selection = NULL; + + nautilus_files_view_call_set_selection (view, selection); + g_list_free_full (selection, g_object_unref); + do_reveal = TRUE; + } + + if (do_reveal) { + if (NAUTILUS_IS_LIST_VIEW (view)) { + /* HACK: We should be able to directly call reveal_selection here, + * but at this point the GtkTreeView hasn't allocated the new nodes + * yet, and it has a bug in the scroll calculation dealing with this + * special case. It would always make the selection the top row, even + * if no scrolling would be neccessary to reveal it. So we let it + * allocate before revealing. + */ + if (view->details->reveal_selection_idle_id != 0) { + g_source_remove (view->details->reveal_selection_idle_id); + } + view->details->reveal_selection_idle_id = + g_idle_add (reveal_selection_idle_callback, view); + } else { + nautilus_files_view_reveal_selection (view); + } + } + nautilus_files_view_display_selection_info (view); + } + + view->details->loading = FALSE; + g_signal_emit (view, signals[END_LOADING], 0, all_files_seen); + + check_empty_states (view); + + nautilus_profile_end (NULL); +} + + +typedef struct { + GHashTable *debuting_files; + GList *added_files; +} DebutingFilesData; + +static void +debuting_files_data_free (DebutingFilesData *data) +{ + g_hash_table_unref (data->debuting_files); + nautilus_file_list_free (data->added_files); + g_free (data); +} + +/* This signal handler watch for the arrival of the icons created + * as the result of a file operation. Once the last one is detected + * it selects and reveals them all. + */ +static void +debuting_files_add_file_callback (NautilusFilesView *view, + NautilusFile *new_file, + NautilusDirectory *directory, + DebutingFilesData *data) +{ + GFile *location; + + nautilus_profile_start (NULL); + + location = nautilus_file_get_location (new_file); + + if (g_hash_table_remove (data->debuting_files, location)) { + nautilus_file_ref (new_file); + data->added_files = g_list_prepend (data->added_files, new_file); + + if (g_hash_table_size (data->debuting_files) == 0) { + nautilus_files_view_call_set_selection (view, data->added_files); + nautilus_files_view_reveal_selection (view); + g_signal_handlers_disconnect_by_func (view, + G_CALLBACK (debuting_files_add_file_callback), + data); + } + } + + nautilus_profile_end (NULL); + + g_object_unref (location); +} + +typedef struct { + GList *added_files; + NautilusFilesView *directory_view; +} CopyMoveDoneData; + +static void +copy_move_done_data_free (CopyMoveDoneData *data) +{ + g_assert (data != NULL); + + if (data->directory_view != NULL) { + g_object_remove_weak_pointer (G_OBJECT (data->directory_view), + (gpointer *) &data->directory_view); + } + + nautilus_file_list_free (data->added_files); + g_free (data); +} + +static void +pre_copy_move_add_file_callback (NautilusFilesView *view, + NautilusFile *new_file, + NautilusDirectory *directory, + CopyMoveDoneData *data) +{ + nautilus_file_ref (new_file); + data->added_files = g_list_prepend (data->added_files, new_file); +} + +/* This needs to be called prior to nautilus_file_operations_copy_move. + * It hooks up a signal handler to catch any icons that get added before + * the copy_done_callback is invoked. The return value should be passed + * as the data for uri_copy_move_done_callback. + */ +static CopyMoveDoneData * +pre_copy_move (NautilusFilesView *directory_view) +{ + CopyMoveDoneData *copy_move_done_data; + + copy_move_done_data = g_new0 (CopyMoveDoneData, 1); + copy_move_done_data->directory_view = directory_view; + + g_object_add_weak_pointer (G_OBJECT (copy_move_done_data->directory_view), + (gpointer *) ©_move_done_data->directory_view); + + /* We need to run after the default handler adds the folder we want to + * operate on. The ADD_FILE signal is registered as G_SIGNAL_RUN_LAST, so we + * must use connect_after. + */ + g_signal_connect (directory_view, "add-file", + G_CALLBACK (pre_copy_move_add_file_callback), copy_move_done_data); + + return copy_move_done_data; +} + +/* This function is used to pull out any debuting uris that were added + * and (as a side effect) remove them from the debuting uri hash table. + */ +static gboolean +copy_move_done_partition_func (gpointer data, + gpointer callback_data) +{ + GFile *location; + gboolean result; + + location = nautilus_file_get_location (NAUTILUS_FILE (data)); + result = g_hash_table_remove ((GHashTable *) callback_data, location); + g_object_unref (location); + + return result; +} + +static gboolean +remove_not_really_moved_files (gpointer key, + gpointer value, + gpointer callback_data) +{ + GList **added_files; + GFile *loc; + + loc = key; + + if (GPOINTER_TO_INT (value)) { + return FALSE; + } + + added_files = callback_data; + *added_files = g_list_prepend (*added_files, + nautilus_file_get (loc)); + return TRUE; +} + +/* When this function is invoked, the file operation is over, but all + * the icons may not have been added to the directory view yet, so + * we can't select them yet. + * + * We're passed a hash table of the uri's to look out for, we hook + * up a signal handler to await their arrival. + */ +static void +copy_move_done_callback (GHashTable *debuting_files, + gboolean success, + gpointer data) +{ + NautilusFilesView *directory_view; + CopyMoveDoneData *copy_move_done_data; + DebutingFilesData *debuting_files_data; + + copy_move_done_data = (CopyMoveDoneData *) data; + directory_view = copy_move_done_data->directory_view; + + if (directory_view != NULL) { + g_assert (NAUTILUS_IS_FILES_VIEW (directory_view)); + + debuting_files_data = g_new (DebutingFilesData, 1); + debuting_files_data->debuting_files = g_hash_table_ref (debuting_files); + debuting_files_data->added_files = eel_g_list_partition + (copy_move_done_data->added_files, + copy_move_done_partition_func, + debuting_files, + ©_move_done_data->added_files); + + /* We're passed the same data used by pre_copy_move_add_file_callback, so disconnecting + * it will free data. We've already siphoned off the added_files we need, and stashed the + * directory_view pointer. + */ + g_signal_handlers_disconnect_by_func (directory_view, + G_CALLBACK (pre_copy_move_add_file_callback), + data); + + /* Any items in the debuting_files hash table that have + * "FALSE" as their value aren't really being copied + * or moved, so we can't wait for an add_file signal + * to come in for those. + */ + g_hash_table_foreach_remove (debuting_files, + remove_not_really_moved_files, + &debuting_files_data->added_files); + + if (g_hash_table_size (debuting_files) == 0) { + /* on the off-chance that all the icons have already been added */ + if (debuting_files_data->added_files != NULL) { + nautilus_files_view_call_set_selection (directory_view, + debuting_files_data->added_files); + nautilus_files_view_reveal_selection (directory_view); + } + debuting_files_data_free (debuting_files_data); + } else { + /* We need to run after the default handler adds the folder we want to + * operate on. The ADD_FILE signal is registered as G_SIGNAL_RUN_LAST, so we + * must use connect_after. + */ + g_signal_connect_data (directory_view, + "add-file", + G_CALLBACK (debuting_files_add_file_callback), + debuting_files_data, + (GClosureNotify) debuting_files_data_free, + G_CONNECT_AFTER); + } + /* Schedule menu update for undo items */ + schedule_update_context_menus (directory_view); + } + + copy_move_done_data_free (copy_move_done_data); +} + +static gboolean +view_file_still_belongs (NautilusFilesView *view, + NautilusFile *file, + NautilusDirectory *directory) +{ + if (view->details->model != directory && + g_list_find (view->details->subdirectory_list, directory) == NULL) { + return FALSE; + } + + return nautilus_directory_contains_file (directory, file); +} + +static gboolean +still_should_show_file (NautilusFilesView *view, + NautilusFile *file, + NautilusDirectory *directory) +{ + return nautilus_files_view_should_show_file (view, file) && + view_file_still_belongs (view, file, directory); +} + +static gboolean +ready_to_load (NautilusFile *file) +{ + return nautilus_file_check_if_ready (file, + NAUTILUS_FILE_ATTRIBUTES_FOR_ICON); +} + +static int +compare_files_cover (gconstpointer a, + gconstpointer b, + gpointer callback_data) +{ + const FileAndDirectory *fad1, *fad2; + NautilusFilesView *view; + + view = callback_data; + fad1 = a; fad2 = b; + + if (fad1->directory < fad2->directory) { + return -1; + } else if (fad1->directory > fad2->directory) { + return 1; + } else { + return NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->compare_files (view, fad1->file, fad2->file); + } +} +static void +sort_files (NautilusFilesView *view, + GList **list) +{ + *list = g_list_sort_with_data (*list, compare_files_cover, view); + +} + +/* Go through all the new added and changed files. + * Put any that are not ready to load in the non_ready_files hash table. + * Add all the rest to the old_added_files and old_changed_files lists. + * Sort the old_*_files lists if anything was added to them. + */ +static void +process_new_files (NautilusFilesView *view) +{ + GList *new_added_files, *new_changed_files, *old_added_files, *old_changed_files; + GHashTable *non_ready_files; + GList *node, *next; + FileAndDirectory *pending; + gboolean in_non_ready; + + new_added_files = view->details->new_added_files; + view->details->new_added_files = NULL; + new_changed_files = view->details->new_changed_files; + view->details->new_changed_files = NULL; + + non_ready_files = view->details->non_ready_files; + + old_added_files = view->details->old_added_files; + old_changed_files = view->details->old_changed_files; + + /* Newly added files go into the old_added_files list if they're + * ready, and into the hash table if they're not. + */ + for (node = new_added_files; node != NULL; node = next) { + next = node->next; + pending = (FileAndDirectory *)node->data; + in_non_ready = g_hash_table_lookup (non_ready_files, pending) != NULL; + if (nautilus_files_view_should_show_file (view, pending->file)) { + if (ready_to_load (pending->file)) { + if (in_non_ready) { + g_hash_table_remove (non_ready_files, pending); + } + new_added_files = g_list_delete_link (new_added_files, node); + old_added_files = g_list_prepend (old_added_files, pending); + } else { + if (!in_non_ready) { + new_added_files = g_list_delete_link (new_added_files, node); + g_hash_table_insert (non_ready_files, pending, pending); + } + } + } + } + file_and_directory_list_free (new_added_files); + + /* Newly changed files go into the old_added_files list if they're ready + * and were seen non-ready in the past, into the old_changed_files list + * if they are read and were not seen non-ready in the past, and into + * the hash table if they're not ready. + */ + for (node = new_changed_files; node != NULL; node = next) { + next = node->next; + pending = (FileAndDirectory *)node->data; + if (!still_should_show_file (view, pending->file, pending->directory) || ready_to_load (pending->file)) { + if (g_hash_table_lookup (non_ready_files, pending) != NULL) { + g_hash_table_remove (non_ready_files, pending); + if (still_should_show_file (view, pending->file, pending->directory)) { + new_changed_files = g_list_delete_link (new_changed_files, node); + old_added_files = g_list_prepend (old_added_files, pending); + } + } else if (nautilus_files_view_should_show_file (view, pending->file)) { + new_changed_files = g_list_delete_link (new_changed_files, node); + old_changed_files = g_list_prepend (old_changed_files, pending); + } + } + } + file_and_directory_list_free (new_changed_files); + + /* If any files were added to old_added_files, then resort it. */ + if (old_added_files != view->details->old_added_files) { + view->details->old_added_files = old_added_files; + sort_files (view, &view->details->old_added_files); + } + + /* Resort old_changed_files too, since file attributes + * relevant to sorting could have changed. + */ + if (old_changed_files != view->details->old_changed_files) { + view->details->old_changed_files = old_changed_files; + sort_files (view, &view->details->old_changed_files); + } + +} + +static void +process_old_files (NautilusFilesView *view) +{ + GList *files_added, *files_changed, *node; + FileAndDirectory *pending; + GList *selection, *files; + gboolean send_selection_change; + + files_added = view->details->old_added_files; + files_changed = view->details->old_changed_files; + + send_selection_change = FALSE; + + if (files_added != NULL || files_changed != NULL) { + g_signal_emit (view, signals[BEGIN_FILE_CHANGES], 0); + + for (node = files_added; node != NULL; node = node->next) { + pending = node->data; + g_signal_emit (view, + signals[ADD_FILE], 0, pending->file, pending->directory); + } + + for (node = files_changed; node != NULL; node = node->next) { + pending = node->data; + g_signal_emit (view, + signals[still_should_show_file (view, pending->file, pending->directory) + ? FILE_CHANGED : REMOVE_FILE], 0, + pending->file, pending->directory); + } + + g_signal_emit (view, signals[END_FILE_CHANGES], 0); + check_empty_states (view); + + if (files_changed != NULL) { + selection = nautilus_files_view_get_selection (view); + files = file_and_directory_list_to_files (files_changed); + send_selection_change = eel_g_lists_sort_and_check_for_intersection + (&files, &selection); + nautilus_file_list_free (files); + nautilus_file_list_free (selection); + } + + file_and_directory_list_free (view->details->old_added_files); + view->details->old_added_files = NULL; + + file_and_directory_list_free (view->details->old_changed_files); + view->details->old_changed_files = NULL; + } + + if (send_selection_change) { + /* Send a selection change since some file names could + * have changed. + */ + nautilus_files_view_send_selection_change (view); + } +} + +static void +display_pending_files (NautilusFilesView *view) +{ + process_new_files (view); + process_old_files (view); + + if (view->details->model != NULL + && nautilus_directory_are_all_files_seen (view->details->model) + && g_hash_table_size (view->details->non_ready_files) == 0) { + done_loading (view, TRUE); + } +} + +static gboolean +display_selection_info_idle_callback (gpointer data) +{ + NautilusFilesView *view; + + view = NAUTILUS_FILES_VIEW (data); + + g_object_ref (G_OBJECT (view)); + + view->details->display_selection_idle_id = 0; + nautilus_files_view_display_selection_info (view); + nautilus_files_view_send_selection_change (view); + + g_object_unref (G_OBJECT (view)); + + return FALSE; +} + +static void +remove_update_context_menus_timeout_callback (NautilusFilesView *view) +{ + 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_context_menus_if_pending (NautilusFilesView *view) +{ + remove_update_context_menus_timeout_callback (view); + + nautilus_files_view_update_context_menus(view); +} + +static gboolean +update_context_menus_timeout_callback (gpointer data) +{ + NautilusFilesView *view; + + view = NAUTILUS_FILES_VIEW (data); + + g_object_ref (G_OBJECT (view)); + + view->details->update_context_menus_timeout_id = 0; + nautilus_files_view_update_context_menus(view); + + g_object_unref (G_OBJECT (view)); + + return FALSE; +} + +static gboolean +display_pending_callback (gpointer data) +{ + NautilusFilesView *view; + + view = NAUTILUS_FILES_VIEW (data); + + g_object_ref (G_OBJECT (view)); + + view->details->display_pending_source_id = 0; + + display_pending_files (view); + + g_object_unref (G_OBJECT (view)); + + return FALSE; +} + +static void +schedule_idle_display_of_pending_files (NautilusFilesView *view) +{ + /* Get rid of a pending source as it might be a timeout */ + unschedule_display_of_pending_files (view); + + /* We want higher priority than the idle that handles the relayout + to avoid a resort on each add. But we still want to allow repaints + and other hight prio events while we have pending files to show. */ + view->details->display_pending_source_id = + g_idle_add_full (G_PRIORITY_DEFAULT_IDLE - 20, + display_pending_callback, view, NULL); +} + +static void +schedule_timeout_display_of_pending_files (NautilusFilesView *view, + guint interval) +{ + /* No need to schedule an update if there's already one pending. */ + if (view->details->display_pending_source_id != 0) { + return; + } + + view->details->display_pending_source_id = + g_timeout_add (interval, display_pending_callback, view); +} + +static void +unschedule_display_of_pending_files (NautilusFilesView *view) +{ + /* Get rid of source if it's active. */ + if (view->details->display_pending_source_id != 0) { + g_source_remove (view->details->display_pending_source_id); + view->details->display_pending_source_id = 0; + } +} + +static void +queue_pending_files (NautilusFilesView *view, + NautilusDirectory *directory, + GList *files, + GList **pending_list) +{ + if (files == NULL) { + return; + } + + *pending_list = g_list_concat (file_and_directory_list_from_files (directory, files), + *pending_list); + + if (! view->details->loading || nautilus_directory_are_all_files_seen (directory)) { + schedule_timeout_display_of_pending_files (view, view->details->update_interval); + } +} + +static void +remove_changes_timeout_callback (NautilusFilesView *view) +{ + if (view->details->changes_timeout_id != 0) { + g_source_remove (view->details->changes_timeout_id); + view->details->changes_timeout_id = 0; + } +} + +static void +reset_update_interval (NautilusFilesView *view) +{ + view->details->update_interval = UPDATE_INTERVAL_MIN; + remove_changes_timeout_callback (view); + /* Reschedule a pending timeout to idle */ + if (view->details->display_pending_source_id != 0) { + schedule_idle_display_of_pending_files (view); + } +} + +static gboolean +changes_timeout_callback (gpointer data) +{ + gint64 now; + gint64 time_delta; + gboolean ret; + NautilusFilesView *view; + + view = NAUTILUS_FILES_VIEW (data); + + g_object_ref (G_OBJECT (view)); + + now = g_get_monotonic_time (); + time_delta = now - view->details->last_queued; + + if (time_delta < UPDATE_INTERVAL_RESET*1000) { + if (view->details->update_interval < UPDATE_INTERVAL_MAX && + view->details->loading) { + /* Increase */ + view->details->update_interval += UPDATE_INTERVAL_INC; + } + ret = TRUE; + } else { + /* Reset */ + reset_update_interval (view); + ret = FALSE; + } + + g_object_unref (G_OBJECT (view)); + + return ret; +} + +static void +schedule_changes (NautilusFilesView *view) +{ + /* Remember when the change was queued */ + view->details->last_queued = g_get_monotonic_time (); + + /* No need to schedule if there are already changes pending or during loading */ + if (view->details->changes_timeout_id != 0 || + view->details->loading) { + return; + } + + view->details->changes_timeout_id = + g_timeout_add (UPDATE_INTERVAL_TIMEOUT_INTERVAL, changes_timeout_callback, view); +} + +static void +files_added_callback (NautilusDirectory *directory, + GList *files, + gpointer callback_data) +{ + NautilusFilesView *view; + GtkWindow *window; + char *uri; + + view = NAUTILUS_FILES_VIEW (callback_data); + + nautilus_profile_start (NULL); + + window = nautilus_files_view_get_containing_window (view); + uri = nautilus_files_view_get_uri (view); + DEBUG_FILES (files, "Files added in window %p: %s", + window, uri ? uri : "(no directory)"); + g_free (uri); + + schedule_changes (view); + + queue_pending_files (view, directory, files, &view->details->new_added_files); + + /* The number of items could have changed */ + schedule_update_status (view); + + nautilus_profile_end (NULL); +} + +static void +files_changed_callback (NautilusDirectory *directory, + GList *files, + gpointer callback_data) +{ + NautilusFilesView *view; + GtkWindow *window; + char *uri; + + view = NAUTILUS_FILES_VIEW (callback_data); + + window = nautilus_files_view_get_containing_window (view); + uri = nautilus_files_view_get_uri (view); + DEBUG_FILES (files, "Files changed in window %p: %s", + window, uri ? uri : "(no directory)"); + g_free (uri); + + schedule_changes (view); + + queue_pending_files (view, directory, files, &view->details->new_changed_files); + + /* The free space or the number of items could have changed */ + schedule_update_status (view); + + /* 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_context_menus (view); +} + +static void +done_loading_callback (NautilusDirectory *directory, + gpointer callback_data) +{ + NautilusFilesView *view; + + view = NAUTILUS_FILES_VIEW (callback_data); + + nautilus_profile_start (NULL); + process_new_files (view); + if (g_hash_table_size (view->details->non_ready_files) == 0) { + /* Unschedule a pending update and schedule a new one with the minimal + * update interval. This gives the view a short chance at gathering the + * (cached) deep counts. + */ + unschedule_display_of_pending_files (view); + schedule_timeout_display_of_pending_files (view, UPDATE_INTERVAL_MIN); + + remove_loading_floating_bar (view); + } + nautilus_profile_end (NULL); +} + +static void +load_error_callback (NautilusDirectory *directory, + GError *error, + gpointer callback_data) +{ + NautilusFilesView *view; + + view = NAUTILUS_FILES_VIEW (callback_data); + + /* FIXME: By doing a stop, we discard some pending files. Is + * that OK? + */ + nautilus_files_view_stop_loading (view); + + nautilus_report_error_loading_directory + (nautilus_files_view_get_directory_as_file (view), + error, + nautilus_files_view_get_containing_window (view)); +} + +void +nautilus_files_view_add_subdirectory (NautilusFilesView *view, + NautilusDirectory *directory) +{ + NautilusFileAttributes attributes; + + g_assert (!g_list_find (view->details->subdirectory_list, directory)); + + nautilus_directory_ref (directory); + + attributes = + NAUTILUS_FILE_ATTRIBUTES_FOR_ICON | + NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT | + NAUTILUS_FILE_ATTRIBUTE_INFO | + NAUTILUS_FILE_ATTRIBUTE_LINK_INFO | + NAUTILUS_FILE_ATTRIBUTE_MOUNT | + NAUTILUS_FILE_ATTRIBUTE_EXTENSION_INFO; + + nautilus_directory_file_monitor_add (directory, + &view->details->model, + view->details->show_hidden_files, + attributes, + files_added_callback, view); + + g_signal_connect + (directory, "files-added", + G_CALLBACK (files_added_callback), view); + g_signal_connect + (directory, "files-changed", + G_CALLBACK (files_changed_callback), view); + + view->details->subdirectory_list = g_list_prepend ( + view->details->subdirectory_list, directory); +} + +void +nautilus_files_view_remove_subdirectory (NautilusFilesView *view, + NautilusDirectory *directory) +{ + g_assert (g_list_find (view->details->subdirectory_list, directory)); + + view->details->subdirectory_list = g_list_remove ( + view->details->subdirectory_list, directory); + + g_signal_handlers_disconnect_by_func (directory, + G_CALLBACK (files_added_callback), + view); + g_signal_handlers_disconnect_by_func (directory, + G_CALLBACK (files_changed_callback), + view); + + nautilus_directory_file_monitor_remove (directory, &view->details->model); + + nautilus_directory_unref (directory); +} + +/** + * nautilus_files_view_get_loading: + * @view: an #NautilusFilesView. + * + * Return value: #gboolean inicating whether @view is currently loaded. + * + **/ +gboolean +nautilus_files_view_get_loading (NautilusFilesView *view) +{ + g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), FALSE); + + return view->details->loading; +} + +/** + * nautilus_files_view_get_model: + * + * Get the model for this NautilusFilesView. + * @view: NautilusFilesView of interest. + * + * Return value: NautilusDirectory for this view. + * + **/ +NautilusDirectory * +nautilus_files_view_get_model (NautilusFilesView *view) +{ + g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), NULL); + + return view->details->model; +} + +GtkWidget* +nautilus_files_view_get_content_widget (NautilusFilesView *view) +{ + g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), NULL); + + return view->details->scrolled_window; +} + +GdkAtom +nautilus_files_view_get_copied_files_atom (NautilusFilesView *view) +{ + g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), GDK_NONE); + + return copied_files_atom; +} + +static void +offset_drop_points (GArray *relative_item_points, + int x_offset, + int y_offset) +{ + guint index; + + if (relative_item_points == NULL) { + return; + } + + for (index = 0; index < relative_item_points->len; index++) { + g_array_index (relative_item_points, GdkPoint, index).x += x_offset; + g_array_index (relative_item_points, GdkPoint, index).y += y_offset; + } +} + +/* special_link_in_selection + * + * Return TRUE if one of our special links is in the selection. + * Special links include the following: + * NAUTILUS_DESKTOP_LINK_TRASH, NAUTILUS_DESKTOP_LINK_HOME, NAUTILUS_DESKTOP_LINK_MOUNT + */ + +static gboolean +special_link_in_selection (GList *selection) +{ + gboolean saw_link; + GList *node; + NautilusFile *file; + + saw_link = FALSE; + + for (node = selection; node != NULL; node = node->next) { + file = NAUTILUS_FILE (node->data); + + saw_link = NAUTILUS_IS_DESKTOP_ICON_FILE (file); + + if (saw_link) { + break; + } + } + + return saw_link; +} + +/* desktop_or_home_dir_in_selection + * + * Return TRUE if either the desktop or the home directory is in the selection. + */ + +static gboolean +desktop_or_home_dir_in_selection (GList *selection) +{ + gboolean saw_desktop_or_home_dir; + GList *node; + NautilusFile *file; + + saw_desktop_or_home_dir = FALSE; + + for (node = selection; node != NULL; node = node->next) { + file = NAUTILUS_FILE (node->data); + + saw_desktop_or_home_dir = + nautilus_file_is_home (file) + || nautilus_file_is_desktop_directory (file); + + if (saw_desktop_or_home_dir) { + break; + } + } + + return saw_desktop_or_home_dir; +} + +static void +trash_or_delete_done_cb (GHashTable *debuting_uris, + gboolean user_cancel, + NautilusFilesView *view) +{ + if (user_cancel) { + view->details->selection_was_removed = FALSE; + } +} + +static void +trash_or_delete_files (GtkWindow *parent_window, + const GList *files, + NautilusFilesView *view) +{ + GList *locations; + const GList *node; + + locations = NULL; + for (node = files; node != NULL; node = node->next) { + locations = g_list_prepend (locations, + nautilus_file_get_location ((NautilusFile *) node->data)); + } + + locations = g_list_reverse (locations); + + nautilus_file_operations_trash_or_delete (locations, + parent_window, + (NautilusDeleteCallback) trash_or_delete_done_cb, + view); + g_list_free_full (locations, g_object_unref); +} + +static gboolean +can_rename_file (NautilusFilesView *view, + NautilusFile *file) +{ + return nautilus_file_can_rename (file); +} + +static void +open_one_in_new_window (gpointer data, + gpointer callback_data) +{ + g_assert (NAUTILUS_IS_FILE (data)); + g_assert (NAUTILUS_IS_FILES_VIEW (callback_data)); + + nautilus_files_view_activate_file (NAUTILUS_FILES_VIEW (callback_data), + NAUTILUS_FILE (data), + NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW); +} + +static void +update_context_menu_position_from_event (NautilusFilesView *view, + GdkEventButton *event) +{ + g_return_if_fail (NAUTILUS_IS_FILES_VIEW (view)); + + if (event != NULL) { + view->details->context_menu_position.x = event->x; + view->details->context_menu_position.y = event->y; + } else { + view->details->context_menu_position.x = -1; + view->details->context_menu_position.y = -1; + } +} + +NautilusFile * +nautilus_files_view_get_directory_as_file (NautilusFilesView *view) +{ + g_assert (NAUTILUS_IS_FILES_VIEW (view)); + + return view->details->directory_as_file; +} + +static GdkPixbuf * +get_menu_icon_for_file (NautilusFile *file, + GtkWidget *widget) +{ + NautilusIconInfo *info; + GdkPixbuf *pixbuf; + int size, scale; + + size = nautilus_get_icon_size_for_stock_size (GTK_ICON_SIZE_MENU); + scale = gtk_widget_get_scale_factor (widget); + + info = nautilus_file_get_icon (file, size, scale, 0); + pixbuf = nautilus_icon_info_get_pixbuf_nodefault_at_size (info, size); + g_object_unref (info); + + return pixbuf; +} + +static GList * +get_extension_selection_menu_items (NautilusFilesView *view) +{ + NautilusWindow *window; + GList *items; + GList *providers; + GList *l; + GList *selection; + + window = nautilus_files_view_get_window (view); + selection = nautilus_files_view_get_selection (view); + 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, + GTK_WIDGET (window), + selection); + items = g_list_concat (items, file_items); + } + + nautilus_module_extension_list_free (providers); + + return items; +} + +static GList * +get_extension_background_menu_items (NautilusFilesView *view) +{ + NautilusWindow *window; + NautilusFile *file; + GList *items; + GList *providers; + GList *l; + + window = nautilus_files_view_get_window (view); + providers = nautilus_module_get_extensions_for_type (NAUTILUS_TYPE_MENU_PROVIDER); + file = nautilus_window_slot_get_file (view->details->slot); + 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_background_items (provider, + GTK_WIDGET (window), + file); + items = g_list_concat (items, file_items); + } + + nautilus_module_extension_list_free (providers); + + return items; +} + +static void +extension_action_callback (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusMenuItem *item = user_data; + nautilus_menu_item_activate (item); +} + +static void +add_extension_action (NautilusFilesView *view, + NautilusMenuItem *item, + const char *action_name) +{ + gboolean sensitive; + GSimpleAction *action; + + g_object_get (item, + "sensitive", &sensitive, + NULL); + + action = g_simple_action_new (action_name, NULL); + g_signal_connect_data (action, "activate", + G_CALLBACK (extension_action_callback), + g_object_ref (item), + (GClosureNotify) g_object_unref, 0); + + g_action_map_add_action (G_ACTION_MAP (view->details->view_action_group), + G_ACTION (action)); + g_simple_action_set_enabled (action, sensitive); + + g_object_unref (action); +} + +static GMenu * +build_menu_for_extension_menu_items (NautilusFilesView *view, + const gchar *extension_prefix, + GList *menu_items) +{ + GList *l; + GMenu *gmenu; + gint idx = 0; + + gmenu = g_menu_new (); + + for (l = menu_items; l; l = l->next) { + NautilusMenuItem *item; + NautilusMenu *menu; + GMenuItem *menu_item; + char *name, *label; + char *extension_id, *prefix, *parsed_name, *detailed_action_name; + + item = NAUTILUS_MENU_ITEM (l->data); + + g_object_get (item, + "label", &label, + "menu", &menu, + "name", &name, + NULL); + + extension_id = g_strdup_printf ("%s_%d", extension_prefix, idx); + prefix = g_strdup_printf ("extension_%s_", extension_id); + parsed_name = nautilus_escape_action_name (name, prefix); + add_extension_action (view, item, parsed_name); + + detailed_action_name = g_strconcat ("view.", parsed_name, NULL); + menu_item = g_menu_item_new (label, detailed_action_name); + + if (menu != NULL) { + GList *children; + GMenu *children_menu; + + children = nautilus_menu_get_items (menu); + children_menu = build_menu_for_extension_menu_items (view, extension_id, children); + g_menu_item_set_submenu (menu_item, G_MENU_MODEL (children_menu)); + + nautilus_menu_item_list_free (children); + g_object_unref (children_menu); + } + + g_menu_append_item (gmenu, menu_item); + idx++; + + g_free (extension_id); + g_free (parsed_name); + g_free (prefix); + g_free (detailed_action_name); + g_free (name); + g_free (label); + g_object_unref (menu_item); + } + + return gmenu; +} + +static void +add_extension_menu_items (NautilusFilesView *view, + const gchar *extension_prefix, + GList *menu_items, + GMenu *insertion_menu) +{ + GMenu *menu; + + menu = build_menu_for_extension_menu_items (view, extension_prefix, menu_items); + nautilus_gmenu_merge (insertion_menu, + menu, + "extensions", + FALSE); + + g_object_unref (menu); +} + +static void +update_extensions_menus (NautilusFilesView *view) +{ + GList *selection_items, *background_items; + + selection_items = get_extension_selection_menu_items (view); + if (selection_items != NULL) { + add_extension_menu_items (view, + "selection", + selection_items, + view->details->selection_menu); + nautilus_menu_item_list_free (selection_items); + } + + background_items = get_extension_background_menu_items (view); + if (background_items != NULL) { + add_extension_menu_items (view, + "background", + background_items, + view->details->background_menu); + nautilus_menu_item_list_free (background_items); + } +} + +static char * +change_to_view_directory (NautilusFilesView *view) +{ + char *path; + char *old_path; + + old_path = g_get_current_dir (); + + path = get_view_directory (view); + + /* FIXME: What to do about non-local directories? */ + if (path != NULL) { + g_chdir (path); + } + + g_free (path); + + return old_path; +} + +static char ** +get_file_names_as_parameter_array (GList *selection, + NautilusDirectory *model) +{ + NautilusFile *file; + char **parameters; + GList *node; + GFile *file_location; + GFile *model_location; + int i; + + if (model == NULL) { + return NULL; + } + + parameters = g_new (char *, g_list_length (selection) + 1); + + model_location = nautilus_directory_get_location (model); + + for (node = selection, i = 0; node != NULL; node = node->next, i++) { + file = NAUTILUS_FILE (node->data); + + if (!nautilus_file_is_local (file)) { + parameters[i] = NULL; + g_strfreev (parameters); + return NULL; + } + + file_location = nautilus_file_get_location (NAUTILUS_FILE (node->data)); + parameters[i] = g_file_get_relative_path (model_location, file_location); + if (parameters[i] == NULL) { + parameters[i] = g_file_get_path (file_location); + } + g_object_unref (file_location); + } + + g_object_unref (model_location); + + parameters[i] = NULL; + return parameters; +} + +static char * +get_file_paths_or_uris_as_newline_delimited_string (GList *selection, + gboolean get_paths) +{ + char *path; + char *uri; + char *result; + NautilusDesktopLink *link; + GString *expanding_string; + GList *node; + GFile *location; + + expanding_string = g_string_new (""); + for (node = selection; node != NULL; node = node->next) { + uri = NULL; + if (NAUTILUS_IS_DESKTOP_ICON_FILE (node->data)) { + link = nautilus_desktop_icon_file_get_link (NAUTILUS_DESKTOP_ICON_FILE (node->data)); + if (link != NULL) { + location = nautilus_desktop_link_get_activation_location (link); + uri = g_file_get_uri (location); + g_object_unref (location); + g_object_unref (G_OBJECT (link)); + } + } else { + uri = nautilus_file_get_uri (NAUTILUS_FILE (node->data)); + } + if (uri == NULL) { + continue; + } + + if (get_paths) { + path = g_filename_from_uri (uri, NULL, NULL); + if (path != NULL) { + g_string_append (expanding_string, path); + g_free (path); + g_string_append (expanding_string, "\n"); + } + } else { + g_string_append (expanding_string, uri); + g_string_append (expanding_string, "\n"); + } + g_free (uri); + } + + result = expanding_string->str; + g_string_free (expanding_string, FALSE); + + return result; +} + +static char * +get_file_paths_as_newline_delimited_string (GList *selection) +{ + return get_file_paths_or_uris_as_newline_delimited_string (selection, TRUE); +} + +static char * +get_file_uris_as_newline_delimited_string (GList *selection) +{ + return get_file_paths_or_uris_as_newline_delimited_string (selection, FALSE); +} + +/* returns newly allocated strings for setting the environment variables */ +static void +get_strings_for_environment_variables (NautilusFilesView *view, + GList *selected_files, + char **file_paths, + char **uris, + char **uri) +{ + char *directory_uri; + + /* We need to check that the directory uri starts with "file:" since + * nautilus_directory_is_local returns FALSE for nfs. + */ + directory_uri = nautilus_directory_get_uri (view->details->model); + if (g_str_has_prefix (directory_uri, "file:") || + eel_uri_is_desktop (directory_uri) || + eel_uri_is_trash (directory_uri)) { + *file_paths = get_file_paths_as_newline_delimited_string (selected_files); + } else { + *file_paths = g_strdup (""); + } + g_free (directory_uri); + + *uris = get_file_uris_as_newline_delimited_string (selected_files); + + *uri = nautilus_directory_get_uri (view->details->model); + if (eel_uri_is_desktop (*uri)) { + g_free (*uri); + *uri = nautilus_get_desktop_directory_uri (); + } +} + +/* + * Set up some environment variables that scripts can use + * to take advantage of the current Nautilus state. + */ +static void +set_script_environment_variables (NautilusFilesView *view, + GList *selected_files) +{ + char *file_paths; + char *uris; + char *uri; + char *geometry_string; + + get_strings_for_environment_variables (view, selected_files, + &file_paths, &uris, &uri); + + g_setenv ("NAUTILUS_SCRIPT_SELECTED_FILE_PATHS", file_paths, TRUE); + g_free (file_paths); + + g_setenv ("NAUTILUS_SCRIPT_SELECTED_URIS", uris, TRUE); + g_free (uris); + + g_setenv ("NAUTILUS_SCRIPT_CURRENT_URI", uri, TRUE); + g_free (uri); + + geometry_string = eel_gtk_window_get_geometry_string + (GTK_WINDOW (nautilus_files_view_get_containing_window (view))); + g_setenv ("NAUTILUS_SCRIPT_WINDOW_GEOMETRY", geometry_string, TRUE); + g_free (geometry_string); +} + +/* Unset all the special script environment variables. */ +static void +unset_script_environment_variables (void) +{ + g_unsetenv ("NAUTILUS_SCRIPT_SELECTED_FILE_PATHS"); + g_unsetenv ("NAUTILUS_SCRIPT_SELECTED_URIS"); + g_unsetenv ("NAUTILUS_SCRIPT_CURRENT_URI"); + g_unsetenv ("NAUTILUS_SCRIPT_WINDOW_GEOMETRY"); +} + +static void +run_script (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + ScriptLaunchParameters *launch_parameters; + GdkScreen *screen; + GList *selected_files; + char *file_uri; + char *local_file_path; + char *quoted_path; + char *old_working_dir; + char **parameters; + + 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); + g_assert (local_file_path != NULL); + g_free (file_uri); + + quoted_path = g_shell_quote (local_file_path); + g_free (local_file_path); + + old_working_dir = change_to_view_directory (launch_parameters->directory_view); + + selected_files = nautilus_files_view_get_selection (launch_parameters->directory_view); + set_script_environment_variables (launch_parameters->directory_view, selected_files); + + parameters = get_file_names_as_parameter_array (selected_files, + launch_parameters->directory_view->details->model); + + screen = gtk_widget_get_screen (GTK_WIDGET (launch_parameters->directory_view)); + + DEBUG ("run_script, script_path=“%s” (omitting script parameters)", + local_file_path); + + nautilus_launch_application_from_command_array (screen, quoted_path, FALSE, + (const char * const *) parameters); + g_strfreev (parameters); + + nautilus_file_list_free (selected_files); + unset_script_environment_variables (); + g_chdir (old_working_dir); + g_free (old_working_dir); + g_free (quoted_path); +} + +static void +add_script_to_scripts_menus (NautilusFilesView *view, + NautilusFile *file, + GMenu *menu) +{ + gchar *name; + GdkPixbuf *mimetype_icon; + gchar *action_name, *detailed_action_name; + ScriptLaunchParameters *launch_parameters; + GAction *action; + GMenuItem *menu_item; + + launch_parameters = script_launch_parameters_new (file, view); + + 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), + launch_parameters, + (GClosureNotify)script_launch_parameters_free, 0); + + 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); + + 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); + } + + g_menu_append_item (menu, menu_item); + + g_free (name); + g_free (action_name); + g_free (detailed_action_name); + g_object_unref (menu_item); +} + +static gboolean +directory_belongs_in_scripts_menu (const char *uri) +{ + int num_levels; + int i; + + if (!g_str_has_prefix (uri, scripts_directory_uri)) { + return FALSE; + } + + num_levels = 0; + for (i = scripts_directory_uri_length; uri[i] != '\0'; i++) { + if (uri[i] == '/') { + num_levels++; + } + } + + if (num_levels > MAX_MENU_LEVELS) { + return FALSE; + } + + return TRUE; +} + +static GMenu * +update_directory_in_scripts_menu (NautilusFilesView *view, + NautilusDirectory *directory) +{ + GList *file_list, *filtered, *node; + GMenu *menu, *children_menu; + GMenuItem *menu_item; + gboolean any_scripts; + NautilusFile *file; + NautilusDirectory *dir; + char *uri; + gchar *file_name; + int num; + + g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), NULL); + g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), NULL); + + 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; 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_scripts_menu (uri)) { + dir = nautilus_directory_get_by_uri (uri); + add_directory_to_scripts_directory_list (view, dir); + + children_menu = update_directory_in_scripts_menu (view, dir); + + if (children_menu != NULL) { + file_name = nautilus_file_get_display_name (file); + menu_item = g_menu_item_new_submenu (file_name, + 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); + g_free (file_name); + } + + 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); + + if (!any_scripts) { + g_object_unref (menu); + menu = NULL; + } + + return menu; +} + + + +static void +update_scripts_menu (NautilusFilesView *view) +{ + GList *sorted_copy, *node; + NautilusDirectory *directory; + GMenu *submenu; + char *uri; + + 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); + } + g_free (uri); + } + nautilus_directory_list_free (sorted_copy); + + 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); + g_object_unref (submenu); + } + + view->details->scripts_present = submenu != NULL; +} + +static void +create_template (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + + CreateTemplateParameters *parameters; + + parameters = user_data; + + nautilus_files_view_new_file (parameters->directory_view, NULL, parameters->file); +} + +static void +add_template_to_templates_menus (NautilusFilesView *view, + NautilusFile *file, + GMenu *menu) +{ + char *tmp, *uri, *name; + GdkPixbuf *mimetype_icon; + char *action_name, *detailed_action_name; + CreateTemplateParameters *parameters; + 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); + action_name = nautilus_escape_action_name (uri, "template_"); + action = G_ACTION (g_simple_action_new (action_name, NULL)); + parameters = create_template_parameters_new (file, view); + + g_signal_connect_data (action, "activate", + 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); + + 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); + } + + g_menu_append_item (menu, menu_item); + + g_free (name); + g_free (uri); + g_free (action_name); + g_free (detailed_action_name); + g_object_unref (action); + g_object_unref (menu_item); +} + +static void +update_templates_directory (NautilusFilesView *view) +{ + NautilusDirectory *templates_directory; + GList *node, *next; + char *templates_uri; + + for (node = view->details->templates_directory_list; node != NULL; node = next) { + next = node->next; + remove_directory_from_templates_directory_list (view, node->data); + } + + 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); + } +} + +static gboolean +directory_belongs_in_templates_menu (const char *templates_directory_uri, + const char *uri) +{ + int num_levels; + int i; + + if (templates_directory_uri == NULL) { + return FALSE; + } + + if (!g_str_has_prefix (uri, templates_directory_uri)) { + return FALSE; + } + + num_levels = 0; + for (i = strlen (templates_directory_uri); uri[i] != '\0'; i++) { + if (uri[i] == '/') { + num_levels++; + } + } + + if (num_levels > MAX_MENU_LEVELS) { + return FALSE; + } + + return TRUE; +} + +static GMenu * +update_directory_in_templates_menu (NautilusFilesView *view, + NautilusDirectory *directory) +{ + GList *file_list, *filtered, *node; + GMenu *menu, *children_menu; + GMenuItem *menu_item; + gboolean any_templates; + NautilusFile *file; + NautilusDirectory *dir; + char *uri; + char *templates_directory_uri; + int num; + + g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), NULL); + g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), NULL); + + 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); + + num = 0; + 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); + + 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); + } + + nautilus_directory_unref (dir); + } + g_free (uri); + } else if (nautilus_file_can_read (file)) { + add_template_to_templates_menus (view, file, menu); + any_templates = TRUE; + } + } + + nautilus_file_list_free (file_list); + g_free (templates_directory_uri); + + if (!any_templates) { + g_object_unref (menu); + menu = NULL; + } + + return menu; +} + + + +static void +update_templates_menu (NautilusFilesView *view) +{ + GList *sorted_copy, *node; + NautilusDirectory *directory; + GMenu *submenu; + char *uri; + char *templates_directory_uri; + + if (nautilus_should_use_templates_directory ()) { + templates_directory_uri = nautilus_get_templates_directory_uri (); + } else { + view->details->templates_present = FALSE; + return; + } + + + 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); + } + g_free (uri); + } + nautilus_directory_list_free (sorted_copy); + + 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); + g_object_unref (submenu); + } + + view->details->templates_present = submenu != NULL; + + g_free (templates_directory_uri); +} + + +static void +action_open_scripts_folder (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusFilesView *view; + static GFile *location = NULL; + + if (location == NULL) { + location = g_file_new_for_uri (scripts_directory_uri); + } + + view = NAUTILUS_FILES_VIEW (user_data); + nautilus_window_slot_open_location (view->details->slot, location, 0); +} + +typedef struct _CopyCallbackData { + NautilusFilesView *view; + GtkFileChooser *chooser; + GHashTable *locations; + GList *selection; + gboolean is_move; +} CopyCallbackData; + +static void +add_bookmark_for_uri (CopyCallbackData *data, + const char *uri) +{ + GError *error = NULL; + int count; + + count = GPOINTER_TO_INT (g_hash_table_lookup (data->locations, uri)); + if (count == 0) { + gtk_file_chooser_add_shortcut_folder_uri (data->chooser, + uri, + &error); + if (error != NULL) { + DEBUG ("Unable to add location '%s' to file selector: %s", uri, error->message); + g_clear_error (&error); + } + } + g_hash_table_replace (data->locations, g_strdup (uri), GINT_TO_POINTER (count + 1)); +} + +static void +remove_bookmark_for_uri (CopyCallbackData *data, + const char *uri) +{ + GError *error = NULL; + int count; + + count = GPOINTER_TO_INT (g_hash_table_lookup (data->locations, uri)); + if (count == 1) { + gtk_file_chooser_remove_shortcut_folder_uri (data->chooser, + uri, + &error); + if (error != NULL) { + DEBUG ("Unable to remove location '%s' to file selector: %s", uri, error->message); + g_clear_error (&error); + } + g_hash_table_remove (data->locations, uri); + } else { + g_hash_table_replace (data->locations, g_strdup (uri), GINT_TO_POINTER (count - 1)); + } +} + +static void +add_bookmarks_for_window_slot (CopyCallbackData *data, + NautilusWindowSlot *slot) +{ + char *uri; + + uri = nautilus_window_slot_get_location_uri (slot); + if (uri != NULL) { + add_bookmark_for_uri (data, uri); + } + g_free (uri); +} + +static void +remove_bookmarks_for_window_slot (CopyCallbackData *data, + NautilusWindowSlot *slot) +{ + char *uri; + + uri = nautilus_window_slot_get_location_uri (slot); + if (uri != NULL) { + remove_bookmark_for_uri (data, uri); + } + g_free (uri); +} + +static void +on_slot_location_changed (NautilusWindowSlot *slot, + const char *from, + const char *to, + CopyCallbackData *data) +{ + if (from != NULL) { + remove_bookmark_for_uri (data, from); + } + + if (to != NULL) { + add_bookmark_for_uri (data, to); + } +} + +static void +on_slot_added (NautilusWindow *window, + NautilusWindowSlot *slot, + CopyCallbackData *data) +{ + add_bookmarks_for_window_slot (data, slot); + g_signal_connect (slot, "location-changed", G_CALLBACK (on_slot_location_changed), data); +} + +static void +on_slot_removed (NautilusWindow *window, + NautilusWindowSlot *slot, + CopyCallbackData *data) +{ + remove_bookmarks_for_window_slot (data, slot); + g_signal_handlers_disconnect_by_func (slot, + G_CALLBACK (on_slot_location_changed), + data); +} + +static void +add_bookmarks_for_window (CopyCallbackData *data, + NautilusWindow *window) +{ + GList *s; + GList *slots; + + slots = nautilus_window_get_slots (window); + for (s = slots; s != NULL; s = s->next) { + NautilusWindowSlot *slot = s->data; + add_bookmarks_for_window_slot (data, slot); + g_signal_connect (slot, "location-changed", G_CALLBACK (on_slot_location_changed), data); + } + g_signal_connect (window, "slot-added", G_CALLBACK (on_slot_added), data); + g_signal_connect (window, "slot-removed", G_CALLBACK (on_slot_removed), data); +} + +static void +remove_bookmarks_for_window (CopyCallbackData *data, + NautilusWindow *window) +{ + GList *s; + GList *slots; + + slots = nautilus_window_get_slots (window); + for (s = slots; s != NULL; s = s->next) { + NautilusWindowSlot *slot = s->data; + remove_bookmarks_for_window_slot (data, slot); + g_signal_handlers_disconnect_by_func (slot, + G_CALLBACK (on_slot_location_changed), + data); + } + g_signal_handlers_disconnect_by_func (window, + G_CALLBACK (on_slot_added), + data); + g_signal_handlers_disconnect_by_func (window, + G_CALLBACK (on_slot_removed), + data); +} + +static void +on_app_window_added (GtkApplication *application, + GtkWindow *window, + CopyCallbackData *data) +{ + add_bookmarks_for_window (data, NAUTILUS_WINDOW (window)); +} + +static void +on_app_window_removed (GtkApplication *application, + GtkWindow *window, + CopyCallbackData *data) +{ + remove_bookmarks_for_window (data, NAUTILUS_WINDOW (window)); +} + +static void +copy_data_free (CopyCallbackData *data) +{ + NautilusApplication *application; + GList *windows; + GList *w; + + application = NAUTILUS_APPLICATION (g_application_get_default ()); + g_signal_handlers_disconnect_by_func (application, + G_CALLBACK (on_app_window_added), + data); + g_signal_handlers_disconnect_by_func (application, + G_CALLBACK (on_app_window_removed), + data); + + windows = nautilus_application_get_windows (application); + for (w = windows; w != NULL; w = w->next) { + NautilusWindow *window = w->data; + GList *slots; + GList *s; + + slots = nautilus_window_get_slots (window); + for (s = slots; s != NULL; s = s->next) { + NautilusWindowSlot *slot = s->data; + g_signal_handlers_disconnect_by_func (slot, G_CALLBACK (on_slot_location_changed), data); + } + g_signal_handlers_disconnect_by_func (window, G_CALLBACK (on_slot_added), data); + g_signal_handlers_disconnect_by_func (window, G_CALLBACK (on_slot_removed), data); + } + + nautilus_file_list_free (data->selection); + g_hash_table_destroy (data->locations); + g_free (data); +} + +static gboolean +uri_is_parent_of_selection (GList *selection, + const char *uri) +{ + gboolean found; + GList *l; + GFile *file; + + found = FALSE; + + file = g_file_new_for_uri (uri); + for (l = selection; !found && l != NULL; l = l->next) { + GFile *parent; + parent = nautilus_file_get_parent_location (l->data); + found = g_file_equal (file, parent); + g_object_unref (parent); + } + g_object_unref (file); + return found; +} + +static void +on_destination_dialog_folder_changed (GtkFileChooser *chooser, + gpointer user_data) +{ + CopyCallbackData *copy_data = user_data; + char *uri; + gboolean found; + + uri = gtk_file_chooser_get_current_folder_uri (chooser); + found = uri_is_parent_of_selection (copy_data->selection, uri); + gtk_dialog_set_response_sensitive (GTK_DIALOG (chooser), GTK_RESPONSE_OK, !found); + g_free (uri); +} + +static void +on_destination_dialog_response (GtkDialog *dialog, + gint response_id, + gpointer user_data) +{ + CopyCallbackData *copy_data = user_data; + + if (response_id == GTK_RESPONSE_OK) { + char *target_uri; + GList *uris, *l; + + target_uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog)); + + uris = NULL; + for (l = copy_data->selection; l != NULL; l = l->next) { + uris = g_list_prepend (uris, + nautilus_file_get_uri ((NautilusFile *) l->data)); + } + uris = g_list_reverse (uris); + + nautilus_files_view_move_copy_items (copy_data->view, uris, NULL, target_uri, + copy_data->is_move ? GDK_ACTION_MOVE : GDK_ACTION_COPY, + 0, 0); + + g_list_free_full (uris, g_free); + g_free (target_uri); + } + + copy_data_free (copy_data); + gtk_widget_destroy (GTK_WIDGET (dialog)); +} + +static gboolean +destination_dialog_filter_cb (const GtkFileFilterInfo *filter_info, + gpointer user_data) +{ + GList *selection = user_data; + GList *l; + + for (l = selection; l != NULL; l = l->next) { + char *uri; + uri = nautilus_file_get_uri (l->data); + if (strcmp (uri, filter_info->uri) == 0) { + g_free (uri); + return FALSE; + } + g_free (uri); + } + + return TRUE; +} + +static GList * +get_selected_folders (GList *selection) +{ + GList *folders; + GList *l; + + folders = NULL; + for (l = selection; l != NULL; l = l->next) { + if (nautilus_file_is_directory (l->data)) + folders = g_list_prepend (folders, nautilus_file_ref (l->data)); + } + return g_list_reverse (folders); +} + +static void +add_window_location_bookmarks (CopyCallbackData *data) +{ + NautilusApplication *application; + GList *windows; + GList *w; + + application = NAUTILUS_APPLICATION (g_application_get_default ()); + windows = nautilus_application_get_windows (application); + g_signal_connect (application, "window-added", G_CALLBACK (on_app_window_added), data); + g_signal_connect (application, "window-removed", G_CALLBACK (on_app_window_removed), data); + + for (w = windows; w != NULL; w = w->next) { + NautilusWindow *window = w->data; + add_bookmarks_for_window (data, window); + } +} + +static void +copy_or_move_selection (NautilusFilesView *view, + gboolean is_move) +{ + GtkWidget *dialog; + char *uri; + CopyCallbackData *copy_data; + GList *selection; + const gchar *title; + + if (is_move) { + title = _("Select Move Destination"); + } else { + title = _("Select Copy Destination"); + } + + selection = nautilus_files_view_get_selection_for_file_transfer (view); + + dialog = gtk_file_chooser_dialog_new (title, + GTK_WINDOW (nautilus_files_view_get_window (view)), + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_Select"), GTK_RESPONSE_OK, + NULL); + gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE); + gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); + + copy_data = g_new0 (CopyCallbackData, 1); + copy_data->view = view; + copy_data->selection = selection; + copy_data->is_move = is_move; + copy_data->chooser = GTK_FILE_CHOOSER (dialog); + copy_data->locations = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + + add_window_location_bookmarks (copy_data); + + if (selection != NULL) { + GtkFileFilter *filter; + GList *folders; + + folders = get_selected_folders (selection); + + filter = gtk_file_filter_new (); + gtk_file_filter_add_custom (filter, + GTK_FILE_FILTER_URI, + destination_dialog_filter_cb, + folders, + (GDestroyNotify)nautilus_file_list_free); + gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter); + } + + uri = nautilus_directory_get_uri (view->details->model); + gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), uri); + g_free (uri); + g_signal_connect (dialog, "current-folder-changed", + G_CALLBACK (on_destination_dialog_folder_changed), + copy_data); + g_signal_connect (dialog, "response", + G_CALLBACK (on_destination_dialog_response), + copy_data); + + gtk_widget_show_all (dialog); +} + +static void +copy_or_cut_files (NautilusFilesView *view, + GList *clipboard_contents, + gboolean cut) +{ + NautilusClipboardInfo info; + GtkTargetList *target_list; + GtkTargetEntry *targets; + int n_targets; + + info.files = clipboard_contents; + info.cut = cut; + + target_list = gtk_target_list_new (NULL, 0); + gtk_target_list_add (target_list, copied_files_atom, 0, 0); + gtk_target_list_add_uri_targets (target_list, 0); + gtk_target_list_add_text_targets (target_list, 0); + + targets = gtk_target_table_new_from_list (target_list, &n_targets); + gtk_target_list_unref (target_list); + + gtk_clipboard_set_with_data (nautilus_clipboard_get (GTK_WIDGET (view)), + targets, n_targets, + nautilus_get_clipboard_callback, nautilus_clear_clipboard_callback, + NULL); + gtk_target_table_free (targets, n_targets); + + nautilus_clipboard_monitor_set_clipboard_info (nautilus_clipboard_monitor_get (), &info); +} + +static void +action_copy (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusFilesView *view; + GList *selection; + + view = NAUTILUS_FILES_VIEW (user_data); + + selection = nautilus_files_view_get_selection_for_file_transfer (view); + copy_or_cut_files (view, selection, FALSE); + nautilus_file_list_free (selection); +} + +static void +action_cut (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusFilesView *view; + GList *selection; + + view = NAUTILUS_FILES_VIEW (user_data); + + selection = nautilus_files_view_get_selection_for_file_transfer (view); + copy_or_cut_files (view, selection, TRUE); + nautilus_file_list_free (selection); +} + +static void +action_copy_to (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusFilesView *view; + + view = NAUTILUS_FILES_VIEW (user_data); + copy_or_move_selection (view, FALSE); +} + +static void +action_move_to (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusFilesView *view; + + view = NAUTILUS_FILES_VIEW (user_data); + copy_or_move_selection (view, TRUE); +} + +typedef struct { + NautilusFilesView *view; + NautilusFile *target; +} PasteIntoData; + +static void +paste_into_clipboard_received_callback (GtkClipboard *clipboard, + GtkSelectionData *selection_data, + gpointer callback_data) +{ + PasteIntoData *data; + NautilusFilesView *view; + char *directory_uri; + + data = (PasteIntoData *) callback_data; + + view = NAUTILUS_FILES_VIEW (data->view); + + if (view->details->slot != NULL) { + directory_uri = nautilus_file_get_activation_uri (data->target); + + paste_clipboard_data (view, selection_data, directory_uri); + + g_free (directory_uri); + } + + g_object_unref (view); + nautilus_file_unref (data->target); + g_free (data); +} + +static void +paste_into (NautilusFilesView *view, + NautilusFile *target) +{ + PasteIntoData *data; + + g_assert (NAUTILUS_IS_FILES_VIEW (view)); + g_assert (NAUTILUS_IS_FILE (target)); + + data = g_new (PasteIntoData, 1); + + data->view = g_object_ref (view); + data->target = nautilus_file_ref (target); + + gtk_clipboard_request_contents (nautilus_clipboard_get (GTK_WIDGET (view)), + copied_files_atom, + paste_into_clipboard_received_callback, + data); +} + +static void +action_paste_files_into (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusFilesView *view; + GList *selection; + + view = NAUTILUS_FILES_VIEW (user_data); + selection = nautilus_files_view_get_selection (view); + if (selection != NULL) { + paste_into (view, NAUTILUS_FILE (selection->data)); + nautilus_file_list_free (selection); + } + +} + +static void +invoke_external_bulk_rename_utility (NautilusFilesView *view, + GList *selection) +{ + GString *cmd; + char *parameter; + char *quoted_parameter; + char *bulk_rename_tool; + GList *walk; + NautilusFile *file; + + /* assemble command line */ + bulk_rename_tool = get_bulk_rename_tool (); + cmd = g_string_new (bulk_rename_tool); + g_free (bulk_rename_tool); + for (walk = selection; walk; walk = walk->next) { + file = walk->data; + parameter = nautilus_file_get_uri (file); + quoted_parameter = g_shell_quote (parameter); + g_free (parameter); + cmd = g_string_append (cmd, " "); + cmd = g_string_append (cmd, quoted_parameter); + g_free (quoted_parameter); + } + + /* spawning and error handling */ + nautilus_launch_application_from_command (gtk_widget_get_screen (GTK_WIDGET (view)), + cmd->str, FALSE, NULL); + g_string_free (cmd, TRUE); +} + +static void +real_action_rename (NautilusFilesView *view, + gboolean select_all) +{ + NautilusFile *file; + GList *selection; + + g_assert (NAUTILUS_IS_FILES_VIEW (view)); + + selection = nautilus_files_view_get_selection (view); + + if (selection_not_empty_in_menu_callback (view, selection)) { + /* If there is more than one file selected, invoke a batch renamer */ + if (selection->next != NULL) { + if (have_bulk_rename_tool ()) { + invoke_external_bulk_rename_utility (view, selection); + } + } else { + file = NAUTILUS_FILE (selection->data); + if (!select_all) { + /* directories don't have a file extension, so + * they are always pre-selected as a whole */ + select_all = nautilus_file_is_directory (file); + } + nautilus_files_view_rename_file_popover_new (view, file); + } + } + + nautilus_file_list_free (selection); +} + +static void +action_rename (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + real_action_rename (NAUTILUS_FILES_VIEW (user_data), FALSE); +} + +#define BG_KEY_PRIMARY_COLOR "primary-color" +#define BG_KEY_SECONDARY_COLOR "secondary-color" +#define BG_KEY_COLOR_TYPE "color-shading-type" +#define BG_KEY_PICTURE_PLACEMENT "picture-options" +#define BG_KEY_PICTURE_URI "picture-uri" + +static void +set_uri_as_wallpaper (const char *uri) +{ + GSettings *settings; + + settings = gnome_background_preferences; + + g_settings_delay (settings); + + if (uri == NULL) + uri = ""; + + g_settings_set_string (settings, BG_KEY_PICTURE_URI, uri); + g_settings_set_string (settings, BG_KEY_PRIMARY_COLOR, "#000000"); + g_settings_set_string (settings, BG_KEY_SECONDARY_COLOR, "#000000"); + g_settings_set_enum (settings, BG_KEY_COLOR_TYPE, G_DESKTOP_BACKGROUND_SHADING_SOLID); + g_settings_set_enum (settings, BG_KEY_PICTURE_PLACEMENT, G_DESKTOP_BACKGROUND_STYLE_ZOOM); + + /* Apply changes atomically. */ + g_settings_apply (settings); +} + +static void +wallpaper_copy_done_callback (GHashTable *debuting_files, + gboolean success, + gpointer data) +{ + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init (&iter, debuting_files); + while (g_hash_table_iter_next (&iter, &key, &value)) { + char *uri; + uri = g_file_get_uri (G_FILE (key)); + set_uri_as_wallpaper (uri); + g_free (uri); + break; + } +} + +static gboolean +can_set_wallpaper (GList *selection) +{ + NautilusFile *file; + + if (g_list_length (selection) != 1) { + return FALSE; + } + + file = NAUTILUS_FILE (selection->data); + if (!nautilus_file_is_mime_type (file, "image/*")) { + return FALSE; + } + + /* FIXME: check file size? */ + + return TRUE; +} + +static void +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_FILES_VIEW (user_data)); + + selection = nautilus_files_view_get_selection (user_data); + + if (can_set_wallpaper (selection) + && selection_not_empty_in_menu_callback (user_data, selection)) { + NautilusFile *file; + char *target_uri; + GList *uris; + GFile *parent; + GFile *target; + + file = NAUTILUS_FILE (selection->data); + + parent = g_file_new_for_path (g_get_user_special_dir (G_USER_DIRECTORY_PICTURES)); + target = g_file_get_child (parent, "Wallpapers"); + g_object_unref (parent); + g_file_make_directory_with_parents (target, NULL, NULL); + target_uri = g_file_get_uri (target); + g_object_unref (target); + uris = g_list_prepend (NULL, nautilus_file_get_uri (file)); + nautilus_file_operations_copy_move (uris, + NULL, + target_uri, + GDK_ACTION_COPY, + GTK_WIDGET (user_data), + wallpaper_copy_done_callback, + NULL); + g_free (target_uri); + g_list_free_full (uris, g_free); + } + + nautilus_file_list_free (selection); +} + +static void +file_mount_callback (NautilusFile *file, + GFile *result_location, + GError *error, + gpointer callback_data) +{ + NautilusFilesView *view; + + view = NAUTILUS_FILES_VIEW (callback_data); + + if (error != NULL && + (error->domain != G_IO_ERROR || + (error->code != G_IO_ERROR_CANCELLED && + error->code != G_IO_ERROR_FAILED_HANDLED && + error->code != G_IO_ERROR_ALREADY_MOUNTED))) { + char *text; + char *name; + name = nautilus_file_get_display_name (file); + /* Translators: %s is a file name formatted for display */ + text = g_strdup_printf (_("Unable to access “%s”"), name); + eel_show_error_dialog (text, error->message, + GTK_WINDOW (nautilus_files_view_get_window (view))); + g_free (text); + g_free (name); + } +} + +static void +file_unmount_callback (NautilusFile *file, + GFile *result_location, + GError *error, + gpointer callback_data) +{ + NautilusFilesView *view; + + view = NAUTILUS_FILES_VIEW (callback_data); + g_object_unref (view); + + if (error != NULL && + (error->domain != G_IO_ERROR || + (error->code != G_IO_ERROR_CANCELLED && + error->code != G_IO_ERROR_FAILED_HANDLED))) { + char *text; + char *name; + name = nautilus_file_get_display_name (file); + /* Translators: %s is a file name formatted for display */ + text = g_strdup_printf (_("Unable to remove “%s”"), name); + eel_show_error_dialog (text, error->message, + GTK_WINDOW (nautilus_files_view_get_window (view))); + g_free (text); + g_free (name); + } +} + +static void +file_eject_callback (NautilusFile *file, + GFile *result_location, + GError *error, + gpointer callback_data) +{ + NautilusFilesView *view; + + view = NAUTILUS_FILES_VIEW (callback_data); + g_object_unref (view); + + if (error != NULL && + (error->domain != G_IO_ERROR || + (error->code != G_IO_ERROR_CANCELLED && + error->code != G_IO_ERROR_FAILED_HANDLED))) { + char *text; + char *name; + name = nautilus_file_get_display_name (file); + /* Translators: %s is a file name formatted for display */ + text = g_strdup_printf (_("Unable to eject “%s”"), name); + eel_show_error_dialog (text, error->message, + GTK_WINDOW (nautilus_files_view_get_window (view))); + g_free (text); + g_free (name); + } +} + +static void +file_stop_callback (NautilusFile *file, + GFile *result_location, + GError *error, + gpointer callback_data) +{ + NautilusFilesView *view; + + view = NAUTILUS_FILES_VIEW (callback_data); + + if (error != NULL && + (error->domain != G_IO_ERROR || + (error->code != G_IO_ERROR_CANCELLED && + error->code != G_IO_ERROR_FAILED_HANDLED))) { + eel_show_error_dialog (_("Unable to stop drive"), + error->message, + GTK_WINDOW (nautilus_files_view_get_window (view))); + } +} + +static void +action_mount_volume (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusFile *file; + GList *selection, *l; + NautilusFilesView *view; + GMountOperation *mount_op; + + view = NAUTILUS_FILES_VIEW (user_data); + + selection = nautilus_files_view_get_selection (view); + for (l = selection; l != NULL; l = l->next) { + file = NAUTILUS_FILE (l->data); + + if (nautilus_file_can_mount (file)) { + mount_op = gtk_mount_operation_new (nautilus_files_view_get_containing_window (view)); + g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION); + nautilus_file_mount (file, mount_op, NULL, + file_mount_callback, + view); + g_object_unref (mount_op); + } + } + nautilus_file_list_free (selection); +} + +static void +action_unmount_volume (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusFile *file; + GList *selection, *l; + NautilusFilesView *view; + + view = NAUTILUS_FILES_VIEW (user_data); + + selection = nautilus_files_view_get_selection (view); + + for (l = selection; l != NULL; l = l->next) { + file = NAUTILUS_FILE (l->data); + if (nautilus_file_can_unmount (file)) { + GMountOperation *mount_op; + mount_op = gtk_mount_operation_new (nautilus_files_view_get_containing_window (view)); + nautilus_file_unmount (file, mount_op, NULL, + file_unmount_callback, g_object_ref (view)); + g_object_unref (mount_op); + } + } + nautilus_file_list_free (selection); +} + +static void +action_eject_volume (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusFile *file; + GList *selection, *l; + NautilusFilesView *view; + + view = NAUTILUS_FILES_VIEW (user_data); + + selection = nautilus_files_view_get_selection (view); + for (l = selection; l != NULL; l = l->next) { + file = NAUTILUS_FILE (l->data); + + if (nautilus_file_can_eject (file)) { + GMountOperation *mount_op; + mount_op = gtk_mount_operation_new (nautilus_files_view_get_containing_window (view)); + nautilus_file_eject (file, mount_op, NULL, + file_eject_callback, g_object_ref (view)); + g_object_unref (mount_op); + } + } + nautilus_file_list_free (selection); +} + +static void +file_start_callback (NautilusFile *file, + GFile *result_location, + GError *error, + gpointer callback_data) +{ + NautilusFilesView *view; + + view = NAUTILUS_FILES_VIEW (callback_data); + + if (error != NULL && + (error->domain != G_IO_ERROR || + (error->code != G_IO_ERROR_CANCELLED && + error->code != G_IO_ERROR_FAILED_HANDLED && + error->code != G_IO_ERROR_ALREADY_MOUNTED))) { + char *text; + char *name; + name = nautilus_file_get_display_name (file); + /* Translators: %s is a file name formatted for display */ + text = g_strdup_printf (_("Unable to start “%s”"), name); + eel_show_error_dialog (text, error->message, + GTK_WINDOW (nautilus_files_view_get_window (view))); + g_free (text); + g_free (name); + } +} + +static void +action_start_volume (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusFile *file; + GList *selection, *l; + NautilusFilesView *view; + GMountOperation *mount_op; + + view = NAUTILUS_FILES_VIEW (user_data); + + selection = nautilus_files_view_get_selection (view); + for (l = selection; l != NULL; l = l->next) { + file = NAUTILUS_FILE (l->data); + + if (nautilus_file_can_start (file) || nautilus_file_can_start_degraded (file)) { + mount_op = gtk_mount_operation_new (nautilus_files_view_get_containing_window (view)); + nautilus_file_start (file, mount_op, NULL, + file_start_callback, view); + g_object_unref (mount_op); + } + } + nautilus_file_list_free (selection); +} + +static void +action_stop_volume (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusFile *file; + GList *selection, *l; + NautilusFilesView *view; + + view = NAUTILUS_FILES_VIEW (user_data); + + selection = nautilus_files_view_get_selection (view); + for (l = selection; l != NULL; l = l->next) { + file = NAUTILUS_FILE (l->data); + + if (nautilus_file_can_stop (file)) { + GMountOperation *mount_op; + mount_op = gtk_mount_operation_new (nautilus_files_view_get_containing_window (view)); + nautilus_file_stop (file, mount_op, NULL, + file_stop_callback, view); + g_object_unref (mount_op); + } + } + nautilus_file_list_free (selection); +} + +static void +action_detect_media (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusFile *file; + GList *selection, *l; + NautilusFilesView *view; + + view = NAUTILUS_FILES_VIEW (user_data); + + selection = nautilus_files_view_get_selection (view); + for (l = selection; l != NULL; l = l->next) { + file = NAUTILUS_FILE (l->data); + + if (nautilus_file_can_poll_for_media (file) && !nautilus_file_is_media_check_automatic (file)) { + nautilus_file_poll_for_media (file); + } + } + nautilus_file_list_free (selection); +} + +const GActionEntry view_entries[] = { + /* Toolbar menu */ + { "zoom-in", action_zoom_in }, + { "zoom-out", action_zoom_out }, + { "zoom-default", action_zoom_default }, + { "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-from-trash", action_delete }, + /* We separate the shortcut and the menu item since we want the shortcut + * to always be available, but we don't want the menu item shown if not + * completely necesary. Since the visibility of the menu item is based on + * the action enability, we need to split the actions for the menu and the + * shortcut. */ + { "delete-permanently-shortcut", action_delete }, + { "delete-permanently-menu-item", action_delete }, + { "remove-from-recent", action_remove_from_recent }, + { "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 }, + /* 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 }, + /* Warning dialog for the change of the shorcut to move to trash */ + { "show-move-to-trash-shortcut-changed-dialog", action_show_move_to_trash_shortcut_changed_dialog } +}; + +static gboolean +can_paste_into_file (NautilusFile *file) +{ + if (nautilus_file_is_directory (file) && + nautilus_file_can_write (file)) { + return TRUE; + } + if (nautilus_file_has_activation_uri (file)) { + GFile *location; + NautilusFile *activation_file; + gboolean res; + + location = nautilus_file_get_activation_location (file); + activation_file = nautilus_file_get (location); + g_object_unref (location); + + /* The target location might not have data for it read yet, + and we can't want to do sync I/O, so treat the unknown + case as can-write */ + res = (nautilus_file_get_file_type (activation_file) == G_FILE_TYPE_UNKNOWN) || + (nautilus_file_get_file_type (activation_file) == G_FILE_TYPE_DIRECTORY && + nautilus_file_can_write (activation_file)); + + nautilus_file_unref (activation_file); + + return res; + } + + return FALSE; +} + +static void +clipboard_targets_received (GtkClipboard *clipboard, + GdkAtom *targets, + int n_targets, + gpointer user_data) +{ + NautilusFilesView *view; + gboolean can_paste; + int i; + GAction *action; + + view = NAUTILUS_FILES_VIEW (user_data); + can_paste = FALSE; + + if (view->details->slot == NULL || + !view->details->active) { + /* We've been destroyed or became inactive since call */ + g_object_unref (view); + return; + } + + if (targets) { + for (i = 0; i < n_targets; i++) { + if (targets[i] == copied_files_atom) { + can_paste = TRUE; + } + } + } + + 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)); + + action = g_action_map_lookup_action (G_ACTION_MAP (view->details->view_action_group), + "paste-into"); + + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + can_paste && g_action_get_enabled (action)); + + g_object_unref (view); +} + +static void +file_should_show_foreach (NautilusFile *file, + gboolean *show_mount, + gboolean *show_unmount, + gboolean *show_eject, + gboolean *show_start, + gboolean *show_stop, + gboolean *show_poll, + GDriveStartStopType *start_stop_type) +{ + *show_mount = FALSE; + *show_unmount = FALSE; + *show_eject = FALSE; + *show_start = FALSE; + *show_stop = FALSE; + *show_poll = FALSE; + + if (nautilus_file_can_eject (file)) { + *show_eject = TRUE; + } + + if (nautilus_file_can_mount (file)) { + *show_mount = TRUE; + } + + if (nautilus_file_can_start (file) || nautilus_file_can_start_degraded (file)) { + *show_start = TRUE; + } + + if (nautilus_file_can_stop (file)) { + *show_stop = TRUE; + } + + /* Dot not show both Unmount and Eject/Safe Removal; too confusing to + * have too many menu entries */ + if (nautilus_file_can_unmount (file) && !*show_eject && !*show_stop) { + *show_unmount = TRUE; + } + + if (nautilus_file_can_poll_for_media (file) && !nautilus_file_is_media_check_automatic (file)) { + *show_poll = TRUE; + } + + *start_stop_type = nautilus_file_get_start_stop_type (file); +} + +static gboolean +can_restore_from_trash (GList *files) +{ + NautilusFile *original_file; + NautilusFile *original_dir; + GHashTable *original_dirs_hash; + GList *original_dirs; + gboolean can_restore; + + original_file = NULL; + original_dir = NULL; + original_dirs = NULL; + original_dirs_hash = NULL; + + if (files != NULL) { + if (g_list_length (files) == 1) { + original_file = nautilus_file_get_trash_original_file (files->data); + } else { + original_dirs_hash = nautilus_trashed_files_get_original_directories (files, NULL); + if (original_dirs_hash != NULL) { + original_dirs = g_hash_table_get_keys (original_dirs_hash); + if (g_list_length (original_dirs) == 1) { + original_dir = nautilus_file_ref (NAUTILUS_FILE (original_dirs->data)); + } + } + } + } + + can_restore = original_file != NULL || original_dirs != NULL; + + nautilus_file_unref (original_file); + nautilus_file_unref (original_dir); + g_list_free (original_dirs); + + if (original_dirs_hash != NULL) { + g_hash_table_destroy (original_dirs_hash); + } + return can_restore; +} + +static void +clipboard_changed_callback (NautilusClipboardMonitor *monitor, + NautilusFilesView *view) +{ + /* Update paste menu item */ + nautilus_files_view_update_context_menus (view); +} + +static gboolean +can_delete_all (GList *files) +{ + NautilusFile *file; + GList *l; + + for (l = files; l != NULL; l = l->next) { + file = l->data; + if (!nautilus_file_can_delete (file)) { + return FALSE; + } + } + return TRUE; +} + +static gboolean +can_trash_all (GList *files) +{ + NautilusFile *file; + GList *l; + + for (l = files; l != NULL; l = l->next) { + file = l->data; + if (!nautilus_file_can_trash (file)) { + return FALSE; + } + } + return TRUE; +} + +static gboolean +all_in_trash (GList *files) +{ + NautilusFile *file; + GList *l; + + for (l = files; l != NULL; l = l->next) { + file = l->data; + if (!nautilus_file_is_in_trash (file)) { + return FALSE; + } + } + return TRUE; +} + +GActionGroup * +nautilus_files_view_get_action_group (NautilusFilesView *view) +{ + g_assert (NAUTILUS_IS_FILES_VIEW (view)); + + return view->details->view_action_group; +} + +static void +real_update_actions_state (NautilusFilesView *view) +{ + GList *selection, *l; + NautilusFile *file; + gint selection_count; + 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_app, show_run; + gboolean item_opens_in_view; + gboolean is_read_only; + GAction *action; + GAppInfo *app; + 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; + + view_action_group = view->details->view_action_group; + + selection = nautilus_files_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 = nautilus_files_view_is_search (view); + selection_is_read_only = selection_count == 1 && + (!nautilus_file_can_write (NAUTILUS_FILE (selection->data)) && + !nautilus_file_has_activation_uri (NAUTILUS_FILE (selection->data))); + selection_all_in_trash = all_in_trash (selection); + + is_read_only = nautilus_files_view_is_read_only (view); + can_create_files = nautilus_files_view_supports_creating_files (view); + can_delete_files = + can_delete_all (selection) && + selection_count != 0 && + !selection_contains_special_link && + !selection_contains_desktop_or_home_dir; + can_trash_files = + can_trash_all (selection) && + selection_count != 0 && + !selection_contains_special_link && + !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; + 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) { + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + have_bulk_rename_tool ()); + } else { + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + selection_count == 1 && + nautilus_files_view_can_rename_file (view, selection->data)); + } + + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "open-item-location"); + + 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_files_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; + + file = NAUTILUS_FILE (selection->data); + + if (!nautilus_mime_file_opens_in_external_app (file)) { + show_app = FALSE; + } + + if (!nautilus_mime_file_launches (file)) { + show_run = FALSE; + } + + if (!nautilus_mime_file_opens_in_view (file)) { + item_opens_in_view = FALSE; + } + + if (!show_app && !show_run && !item_opens_in_view) { + break; + } + } + + /* Open With <App> menu item */ + app = NULL; + if (show_app) { + app = nautilus_mime_get_default_application_for_files (selection); + } + + 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 || + (selection_count > 0 && + nautilus_file_is_directory (NAUTILUS_FILE (selection->data)))); + + 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-from-trash"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + can_delete_files && selection_all_in_trash); + + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "delete-permanently-shortcut"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + can_delete_files); + + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "delete-permanently-menu-item"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + can_delete_files && !can_trash_files && + !selection_all_in_trash && !selection_contains_recent); + + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "remove-from-recent"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + selection_contains_recent && selection_count > 0); + + 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; + + 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_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); + + /* 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); + + action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), + "select-all"); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), + !nautilus_files_view_is_empty (view)); + + /* Toolbar menu actions */ + 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_files_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_files_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_files_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_files_view_update_actions_state (NautilusFilesView *view) +{ + g_assert(NAUTILUS_IS_FILES_VIEW (view)); + + NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->update_actions_state (view); +} + +static void +update_selection_menu (NautilusFilesView *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; + + selection = nautilus_files_view_get_selection (view); + selection_count = g_list_length (selection); + + 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); + start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN; + item_label = g_strdup_printf (ngettext ("New Folder with Selection (%'d Item)", + "New Folder with Selection (%'d Items)", + selection_count), + 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; + + file = NAUTILUS_FILE (selection->data); + + if (!nautilus_mime_file_opens_in_external_app (file)) { + show_app = FALSE; + } + + if (!nautilus_mime_file_launches (file)) { + show_run = FALSE; + } + + if (!nautilus_mime_file_opens_in_view (file)) { + item_opens_in_view = FALSE; + } + + if (!show_app && !show_run && !item_opens_in_view) { + break; + } + } + + item_label = NULL; + app = NULL; + app_icon = NULL; + if (show_app) { + app = nautilus_mime_get_default_application_for_files (selection); + } + + char *escaped_app; + + 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); + + 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 { + item_label = g_strdup (_("Open")); + } + + 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); + + nautilus_gmenu_add_item_in_submodel (view->details->selection_menu, + menu_item, + "open-with-default-application-section", + FALSE); + + 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; + + 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_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; + } + + 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; + } + + 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 (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); + } + + update_scripts_menu (view); +} + +static void +update_background_menu (NautilusFilesView *view) +{ + + if (nautilus_files_view_supports_creating_files (view) && + !showing_recent_directory (view)) + update_templates_menu (view); +} + +static void +real_update_context_menus (NautilusFilesView *view) +{ + g_clear_object (&view->details->background_menu); + g_clear_object (&view->details->selection_menu); + + GtkBuilder *builder; + builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/nautilus-files-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"))); + g_object_unref (builder); + + update_selection_menu (view); + update_background_menu (view); + update_extensions_menus (view); + + nautilus_files_view_update_actions_state (view); +} + +/* 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_files_view_update_actions_state + */ +void +nautilus_files_view_update_context_menus (NautilusFilesView *view) +{ + g_assert(NAUTILUS_IS_FILES_VIEW (view)); + + NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->update_context_menus (view); +} + +static void +nautilus_files_view_reset_view_menu (NautilusFilesView *view) +{ + GActionGroup *view_action_group; + GVariant *variant; + GVariantIter iter; + gboolean show_sort_trash, show_sort_search, show_sort_access, show_sort_modification, enable_sort; + const gchar *hint; + + view_action_group = nautilus_files_view_get_action_group (view); + + gtk_widget_set_visible (view->details->visible_columns, + g_action_group_has_action (view_action_group, "visible-columns")); + + enable_sort = g_action_group_get_action_enabled (view_action_group, "sort"); + show_sort_trash = show_sort_search = show_sort_modification = show_sort_access = FALSE; + gtk_widget_set_visible (view->details->sort_menu, enable_sort); + + if (enable_sort) { + variant = g_action_group_get_action_state_hint (view_action_group, "sort"); + g_variant_iter_init (&iter, variant); + + while (g_variant_iter_next (&iter, "&s", &hint)) { + if (g_strcmp0 (hint, "trash-time") == 0) + show_sort_trash = TRUE; + if (g_strcmp0 (hint, "search-relevance") == 0) + show_sort_search = TRUE; + } + + g_variant_unref (variant); + } + + gtk_widget_set_visible (view->details->sort_trash_time, show_sort_trash); + gtk_widget_set_visible (view->details->sort_search_relevance, show_sort_search); + + variant = g_action_group_get_action_state (view_action_group, "zoom-to-level"); + gtk_adjustment_set_value (view->details->zoom_adjustment, + g_variant_get_int32 (variant)); + g_variant_unref (variant); +} + +/* Convenience function to reset the menus owned by the view but managed on + * the toolbar, and update them with the current state. + * It will also update the actions state, which will also update children + * actions state if the children subclass nautilus_files_view_update_actions_state + */ +void +nautilus_files_view_update_toolbar_menus (NautilusFilesView *view) +{ + NautilusWindow *window; + + g_assert (NAUTILUS_IS_FILES_VIEW (view)); + + /* Don't update after destroy (#349551), + * or if we are not active. + */ + if (view->details->slot == NULL || + !view->details->active) { + return; + } + window = nautilus_files_view_get_window (view); + nautilus_window_reset_menus (window); + + nautilus_files_view_reset_view_menu (view); + nautilus_files_view_update_actions_state (view); +} + +/** + * nautilus_files_view_pop_up_selection_context_menu + * + * Pop up a context menu appropriate to the selected items. + * @view: NautilusFilesView of interest. + * @event: The event that triggered this context menu. + * + **/ +void +nautilus_files_view_pop_up_selection_context_menu (NautilusFilesView *view, + GdkEventButton *event) +{ + g_assert (NAUTILUS_IS_FILES_VIEW (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, event); + + nautilus_pop_up_context_menu (GTK_WIDGET (view), view->details->selection_menu, event); +} + +/** + * nautilus_files_view_pop_up_background_context_menu + * + * Pop up a context menu appropriate to the view globally at the last right click location. + * @view: NautilusFilesView of interest. + * + **/ +void +nautilus_files_view_pop_up_background_context_menu (NautilusFilesView *view, + GdkEventButton *event) +{ + g_assert (NAUTILUS_IS_FILES_VIEW (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, event); + + nautilus_pop_up_context_menu (GTK_WIDGET (view), view->details->background_menu, event); +} + +static void +schedule_update_context_menus (NautilusFilesView *view) +{ + g_assert (NAUTILUS_IS_FILES_VIEW (view)); + + /* Don't schedule updates after destroy (#349551), + * or if we are not active. + */ + if (view->details->slot == NULL || + !view->details->active) { + return; + } + + /* Schedule a menu update with the current update interval */ + 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); + } +} + +static void +remove_update_status_idle_callback (NautilusFilesView *view) +{ + if (view->details->update_status_idle_id != 0) { + g_source_remove (view->details->update_status_idle_id); + view->details->update_status_idle_id = 0; + } +} + +static gboolean +update_status_idle_callback (gpointer data) +{ + NautilusFilesView *view; + + view = NAUTILUS_FILES_VIEW (data); + nautilus_files_view_display_selection_info (view); + view->details->update_status_idle_id = 0; + return FALSE; +} + +static void +schedule_update_status (NautilusFilesView *view) +{ + g_assert (NAUTILUS_IS_FILES_VIEW (view)); + + /* Make sure we haven't already destroyed it */ + if (view->details->slot == NULL) { + return; + } + + if (view->details->loading) { + /* Don't update status bar while loading the dir */ + return; + } + + if (view->details->update_status_idle_id == 0) { + view->details->update_status_idle_id = + g_idle_add_full (G_PRIORITY_DEFAULT_IDLE - 20, + update_status_idle_callback, view, NULL); + } +} + +/** + * nautilus_files_view_notify_selection_changed: + * + * Notify this view that the selection has changed. This is normally + * called only by subclasses. + * @view: NautilusFilesView whose selection has changed. + * + **/ +void +nautilus_files_view_notify_selection_changed (NautilusFilesView *view) +{ + GtkWindow *window; + GList *selection; + + g_return_if_fail (NAUTILUS_IS_FILES_VIEW (view)); + + selection = nautilus_files_view_get_selection (view); + window = nautilus_files_view_get_containing_window (view); + DEBUG_FILES (selection, "Selection changed in window %p", window); + nautilus_file_list_free (selection); + + view->details->selection_was_removed = FALSE; + + /* Schedule a display of the new selection. */ + if (view->details->display_selection_idle_id == 0) { + view->details->display_selection_idle_id + = g_idle_add (display_selection_info_idle_callback, + view); + } + + if (view->details->batching_selection_level != 0) { + view->details->selection_changed_while_batched = TRUE; + } else { + /* Here is the work we do only when we're not + * batching selection changes. In other words, it's the slower + * stuff that we don't want to slow down selection techniques + * such as rubberband-selecting in icon view. + */ + + /* Schedule an update of menu item states to match selection */ + schedule_update_context_menus (view); + } +} + +static void +file_changed_callback (NautilusFile *file, + gpointer callback_data) +{ + NautilusFilesView *view = NAUTILUS_FILES_VIEW (callback_data); + + schedule_changes (view); + + schedule_update_context_menus (view); + schedule_update_status (view); +} + +/** + * load_directory: + * + * Switch the displayed location to a new uri. If the uri is not valid, + * the location will not be switched; user feedback will be provided instead. + * @view: NautilusFilesView whose location will be changed. + * @uri: A string representing the uri to switch to. + * + **/ +static void +load_directory (NautilusFilesView *view, + NautilusDirectory *directory) +{ + NautilusDirectory *old_directory; + NautilusFile *old_file; + NautilusFileAttributes attributes; + + g_assert (NAUTILUS_IS_FILES_VIEW (view)); + g_assert (NAUTILUS_IS_DIRECTORY (directory)); + + nautilus_profile_start (NULL); + + nautilus_files_view_stop_loading (view); + g_signal_emit (view, signals[CLEAR], 0); + + view->details->loading = TRUE; + + setup_loading_floating_bar (view); + + /* Update menus when directory is empty, before going to new + * location, so they won't have any false lingering knowledge + * of old selection. + */ + schedule_update_context_menus (view); + + while (view->details->subdirectory_list != NULL) { + nautilus_files_view_remove_subdirectory (view, + view->details->subdirectory_list->data); + } + + old_directory = view->details->model; + + nautilus_directory_ref (directory); + view->details->model = directory; + nautilus_directory_unref (old_directory); + + old_file = view->details->directory_as_file; + view->details->directory_as_file = + nautilus_directory_get_corresponding_file (directory); + nautilus_file_unref (old_file); + + /* FIXME bugzilla.gnome.org 45062: In theory, we also need to monitor metadata here (as + * well as doing a call when ready), in case external forces + * change the directory's file metadata. + */ + attributes = + NAUTILUS_FILE_ATTRIBUTE_INFO | + NAUTILUS_FILE_ATTRIBUTE_MOUNT | + NAUTILUS_FILE_ATTRIBUTE_FILESYSTEM_INFO; + view->details->metadata_for_directory_as_file_pending = TRUE; + view->details->metadata_for_files_in_directory_pending = TRUE; + nautilus_file_call_when_ready + (view->details->directory_as_file, + attributes, + metadata_for_directory_as_file_ready_callback, view); + nautilus_directory_call_when_ready + (view->details->model, + attributes, + FALSE, + metadata_for_files_in_directory_ready_callback, view); + + /* If capabilities change, then we need to update the menus + * because of New Folder, and relative emblems. + */ + attributes = + NAUTILUS_FILE_ATTRIBUTE_INFO | + NAUTILUS_FILE_ATTRIBUTE_FILESYSTEM_INFO; + nautilus_file_monitor_add (view->details->directory_as_file, + &view->details->directory_as_file, + attributes); + + view->details->file_changed_handler_id = g_signal_connect + (view->details->directory_as_file, "changed", + G_CALLBACK (file_changed_callback), view); + + nautilus_profile_end (NULL); +} + +static void +finish_loading (NautilusFilesView *view) +{ + NautilusFileAttributes attributes; + + nautilus_profile_start (NULL); + + /* Tell interested parties that we've begun loading this directory now. + * Subclasses use this to know that the new metadata is now available. + */ + nautilus_profile_start ("BEGIN_LOADING"); + g_signal_emit (view, signals[BEGIN_LOADING], 0); + nautilus_profile_end ("BEGIN_LOADING"); + + check_empty_states (view); + + if (nautilus_directory_are_all_files_seen (view->details->model)) { + /* Unschedule a pending update and schedule a new one with the minimal + * update interval. This gives the view a short chance at gathering the + * (cached) deep counts. + */ + unschedule_display_of_pending_files (view); + schedule_timeout_display_of_pending_files (view, UPDATE_INTERVAL_MIN); + } + + /* Start loading. */ + + /* Connect handlers to learn about loading progress. */ + view->details->done_loading_handler_id = g_signal_connect + (view->details->model, "done-loading", + G_CALLBACK (done_loading_callback), view); + view->details->load_error_handler_id = g_signal_connect + (view->details->model, "load-error", + G_CALLBACK (load_error_callback), view); + + /* Monitor the things needed to get the right icon. Also + * monitor a directory's item count because the "size" + * attribute is based on that, and the file's metadata + * and possible custom name. + */ + attributes = + NAUTILUS_FILE_ATTRIBUTES_FOR_ICON | + NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT | + NAUTILUS_FILE_ATTRIBUTE_INFO | + NAUTILUS_FILE_ATTRIBUTE_LINK_INFO | + NAUTILUS_FILE_ATTRIBUTE_MOUNT | + NAUTILUS_FILE_ATTRIBUTE_EXTENSION_INFO; + + nautilus_directory_file_monitor_add (view->details->model, + &view->details->model, + view->details->show_hidden_files, + attributes, + files_added_callback, view); + + view->details->files_added_handler_id = g_signal_connect + (view->details->model, "files-added", + G_CALLBACK (files_added_callback), view); + view->details->files_changed_handler_id = g_signal_connect + (view->details->model, "files-changed", + G_CALLBACK (files_changed_callback), view); + + nautilus_profile_end (NULL); +} + +static void +finish_loading_if_all_metadata_loaded (NautilusFilesView *view) +{ + if (!view->details->metadata_for_directory_as_file_pending && + !view->details->metadata_for_files_in_directory_pending) { + finish_loading (view); + } +} + +static void +metadata_for_directory_as_file_ready_callback (NautilusFile *file, + gpointer callback_data) +{ + NautilusFilesView *view; + + view = callback_data; + + g_assert (NAUTILUS_IS_FILES_VIEW (view)); + g_assert (view->details->directory_as_file == file); + g_assert (view->details->metadata_for_directory_as_file_pending); + + nautilus_profile_start (NULL); + + view->details->metadata_for_directory_as_file_pending = FALSE; + + finish_loading_if_all_metadata_loaded (view); + nautilus_profile_end (NULL); +} + +static void +metadata_for_files_in_directory_ready_callback (NautilusDirectory *directory, + GList *files, + gpointer callback_data) +{ + NautilusFilesView *view; + + view = callback_data; + + g_assert (NAUTILUS_IS_FILES_VIEW (view)); + g_assert (view->details->model == directory); + g_assert (view->details->metadata_for_files_in_directory_pending); + + nautilus_profile_start (NULL); + + view->details->metadata_for_files_in_directory_pending = FALSE; + + finish_loading_if_all_metadata_loaded (view); + nautilus_profile_end (NULL); +} + +static void +disconnect_handler (GObject *object, + guint *id) +{ + if (*id != 0) { + g_signal_handler_disconnect (object, *id); + *id = 0; + } +} + +static void +disconnect_directory_handler (NautilusFilesView *view, + guint *id) +{ + disconnect_handler (G_OBJECT (view->details->model), id); +} + +static void +disconnect_directory_as_file_handler (NautilusFilesView *view, + guint *id) +{ + disconnect_handler (G_OBJECT (view->details->directory_as_file), id); +} + +static void +disconnect_model_handlers (NautilusFilesView *view) +{ + if (view->details->model == NULL) { + return; + } + disconnect_directory_handler (view, &view->details->files_added_handler_id); + disconnect_directory_handler (view, &view->details->files_changed_handler_id); + disconnect_directory_handler (view, &view->details->done_loading_handler_id); + disconnect_directory_handler (view, &view->details->load_error_handler_id); + disconnect_directory_as_file_handler (view, &view->details->file_changed_handler_id); + nautilus_file_cancel_call_when_ready (view->details->directory_as_file, + metadata_for_directory_as_file_ready_callback, + view); + nautilus_directory_cancel_callback (view->details->model, + metadata_for_files_in_directory_ready_callback, + view); + nautilus_directory_file_monitor_remove (view->details->model, + &view->details->model); + nautilus_file_monitor_remove (view->details->directory_as_file, + &view->details->directory_as_file); +} + +static void +nautilus_files_view_select_file (NautilusFilesView *view, + NautilusFile *file) +{ + GList file_list; + + file_list.data = file; + file_list.next = NULL; + file_list.prev = NULL; + nautilus_files_view_call_set_selection (view, &file_list); +} + +static gboolean +remove_all (gpointer key, + gpointer value, + gpointer callback_data) +{ + return TRUE; +} + +/** + * nautilus_files_view_stop_loading: + * + * Stop the current ongoing process, such as switching to a new uri. + * @view: NautilusFilesView in question. + * + **/ +void +nautilus_files_view_stop_loading (NautilusFilesView *view) +{ + g_return_if_fail (NAUTILUS_IS_FILES_VIEW (view)); + + disconnect_model_handlers (view); + if (view->details->model) { + nautilus_directory_unref (view->details->model); + view->details->model = NULL; + } + unschedule_display_of_pending_files (view); + reset_update_interval (view); + + /* Free extra undisplayed files */ + file_and_directory_list_free (view->details->new_added_files); + view->details->new_added_files = NULL; + + file_and_directory_list_free (view->details->new_changed_files); + view->details->new_changed_files = NULL; + + g_hash_table_foreach_remove (view->details->non_ready_files, remove_all, NULL); + + file_and_directory_list_free (view->details->old_added_files); + view->details->old_added_files = NULL; + + file_and_directory_list_free (view->details->old_changed_files); + view->details->old_changed_files = NULL; + + g_list_free_full (view->details->pending_selection, g_object_unref); + view->details->pending_selection = NULL; + + done_loading (view, FALSE); +} + +gboolean +nautilus_files_view_is_editable (NautilusFilesView *view) +{ + NautilusDirectory *directory; + + directory = nautilus_files_view_get_model (view); + + if (directory != NULL) { + return nautilus_directory_is_editable (directory); + } + + return TRUE; +} + +static gboolean +real_is_read_only (NautilusFilesView *view) +{ + NautilusFile *file; + + if (!nautilus_files_view_is_editable (view)) { + return TRUE; + } + + file = nautilus_files_view_get_directory_as_file (view); + if (file != NULL) { + return !nautilus_file_can_write (file); + } + return FALSE; +} + +/** + * nautilus_files_view_should_show_file + * + * Returns whether or not this file should be displayed based on + * current filtering options. + */ +gboolean +nautilus_files_view_should_show_file (NautilusFilesView *view, + NautilusFile *file) +{ + return nautilus_file_should_show (file, + view->details->show_hidden_files, + view->details->show_foreign_files); +} + +static gboolean +real_using_manual_layout (NautilusFilesView *view) +{ + g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), FALSE); + + return FALSE; +} + +void +nautilus_files_view_ignore_hidden_file_preferences (NautilusFilesView *view) +{ + g_return_if_fail (view->details->model == NULL); + + if (view->details->ignore_hidden_file_preferences) { + return; + } + + view->details->show_hidden_files = FALSE; + view->details->ignore_hidden_file_preferences = TRUE; +} + +void +nautilus_files_view_set_show_foreign (NautilusFilesView *view, + gboolean show_foreign) +{ + view->details->show_foreign_files = show_foreign; +} + +char * +nautilus_files_view_get_uri (NautilusFilesView *view) +{ + g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), NULL); + if (view->details->model == NULL) { + return NULL; + } + return nautilus_directory_get_uri (view->details->model); +} + +void +nautilus_files_view_move_copy_items (NautilusFilesView *view, + const GList *item_uris, + GArray *relative_item_points, + const char *target_uri, + int copy_action, + int x, + int y) +{ + NautilusFile *target_file; + + g_assert (relative_item_points == NULL + || relative_item_points->len == 0 + || g_list_length ((GList *)item_uris) == relative_item_points->len); + + /* add the drop location to the icon offsets */ + offset_drop_points (relative_item_points, x, y); + + target_file = nautilus_file_get_existing_by_uri (target_uri); + /* special-case "command:" here instead of starting a move/copy */ + if (target_file != NULL && nautilus_file_is_launcher (target_file)) { + nautilus_file_unref (target_file); + nautilus_launch_desktop_file ( + gtk_widget_get_screen (GTK_WIDGET (view)), + target_uri, item_uris, + nautilus_files_view_get_containing_window (view)); + return; + } else if (copy_action == GDK_ACTION_COPY && + nautilus_is_file_roller_installed () && + target_file != NULL && + nautilus_file_is_archive (target_file)) { + char *command, *quoted_uri, *tmp; + const GList *l; + GdkScreen *screen; + + /* Handle dropping onto a file-roller archiver file, instead of starting a move/copy */ + + nautilus_file_unref (target_file); + + quoted_uri = g_shell_quote (target_uri); + command = g_strconcat ("file-roller -a ", quoted_uri, NULL); + g_free (quoted_uri); + + for (l = item_uris; l != NULL; l = l->next) { + quoted_uri = g_shell_quote ((char *) l->data); + + tmp = g_strconcat (command, " ", quoted_uri, NULL); + g_free (command); + command = tmp; + + g_free (quoted_uri); + } + + screen = gtk_widget_get_screen (GTK_WIDGET (view)); + if (screen == NULL) { + screen = gdk_screen_get_default (); + } + + nautilus_launch_application_from_command (screen, command, FALSE, NULL); + g_free (command); + + return; + } + nautilus_file_unref (target_file); + + nautilus_file_operations_copy_move + (item_uris, relative_item_points, + target_uri, copy_action, GTK_WIDGET (view), + copy_move_done_callback, pre_copy_move (view)); +} + +static void +nautilus_files_view_trash_state_changed_callback (NautilusTrashMonitor *trash_monitor, + gboolean state, + gpointer callback_data) +{ + NautilusFilesView *view; + + view = (NautilusFilesView *) callback_data; + g_assert (NAUTILUS_IS_FILES_VIEW (view)); + + schedule_update_context_menus (view); +} + +void +nautilus_files_view_start_batching_selection_changes (NautilusFilesView *view) +{ + g_return_if_fail (NAUTILUS_IS_FILES_VIEW (view)); + + ++view->details->batching_selection_level; + view->details->selection_changed_while_batched = FALSE; +} + +void +nautilus_files_view_stop_batching_selection_changes (NautilusFilesView *view) +{ + g_return_if_fail (NAUTILUS_IS_FILES_VIEW (view)); + g_return_if_fail (view->details->batching_selection_level > 0); + + if (--view->details->batching_selection_level == 0) { + if (view->details->selection_changed_while_batched) { + nautilus_files_view_notify_selection_changed (view); + } + } +} + +static GArray * +real_get_selected_icon_locations (NautilusFilesView *view) +{ + /* By default, just return an empty list. */ + return g_array_new (FALSE, TRUE, sizeof (GdkPoint)); +} + +static void +nautilus_files_view_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NautilusFilesView *view = NAUTILUS_FILES_VIEW (object); + + switch (prop_id) { + case PROP_ICON: + g_value_set_object (value, nautilus_files_view_get_icon (view)); + break; + + case PROP_VIEW_WIDGET: + g_value_set_object (value, nautilus_files_view_get_view_widget (view)); + break; + + default: + g_assert_not_reached (); + + } +} + +static void +nautilus_files_view_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + NautilusFilesView *directory_view; + NautilusWindowSlot *slot; + + directory_view = NAUTILUS_FILES_VIEW (object); + + switch (prop_id) { + case PROP_WINDOW_SLOT: + g_assert (directory_view->details->slot == NULL); + + slot = NAUTILUS_WINDOW_SLOT (g_value_get_object (value)); + directory_view->details->slot = slot; + + g_signal_connect_object (directory_view->details->slot, + "active", G_CALLBACK (slot_active), + directory_view, 0); + g_signal_connect_object (directory_view->details->slot, + "inactive", G_CALLBACK (slot_inactive), + directory_view, 0); + break; + case PROP_SUPPORTS_ZOOMING: + directory_view->details->supports_zooming = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +gboolean +nautilus_files_view_handle_scroll_event (NautilusFilesView *directory_view, + GdkEventScroll *event) +{ + static gdouble total_delta_y = 0; + gdouble delta_x, delta_y; + + if (event->state & GDK_CONTROL_MASK) { + switch (event->direction) { + case GDK_SCROLL_UP: + /* Zoom In */ + nautilus_files_view_bump_zoom_level (directory_view, 1); + return TRUE; + + case GDK_SCROLL_DOWN: + /* Zoom Out */ + nautilus_files_view_bump_zoom_level (directory_view, -1); + return TRUE; + + case GDK_SCROLL_SMOOTH: + gdk_event_get_scroll_deltas ((const GdkEvent *) event, + &delta_x, &delta_y); + + /* try to emulate a normal scrolling event by summing deltas */ + total_delta_y += delta_y; + + if (total_delta_y >= 1) { + total_delta_y = 0; + /* emulate scroll down */ + nautilus_files_view_bump_zoom_level (directory_view, -1); + return TRUE; + } else if (total_delta_y <= - 1) { + total_delta_y = 0; + /* emulate scroll up */ + nautilus_files_view_bump_zoom_level (directory_view, 1); + return TRUE; + } else { + /* eat event */ + return TRUE; + } + + case GDK_SCROLL_LEFT: + case GDK_SCROLL_RIGHT: + break; + + default: + g_assert_not_reached (); + } + } + + return FALSE; +} + +/* handle Shift+Scroll, which will cause a zoom-in/out */ +static gboolean +nautilus_files_view_scroll_event (GtkWidget *widget, + GdkEventScroll *event) +{ + NautilusFilesView *directory_view; + + directory_view = NAUTILUS_FILES_VIEW (widget); + if (nautilus_files_view_handle_scroll_event (directory_view, event)) { + return TRUE; + } + + return FALSE; +} + + +static void +action_reload_enabled_changed (GActionGroup *action_group, + gchar *action_name, + gboolean enabled, + NautilusFilesView *view) +{ + gtk_widget_set_visible (view->details->reload, enabled); +} + +static void +action_stop_enabled_changed (GActionGroup *action_group, + gchar *action_name, + gboolean enabled, + NautilusFilesView *view) +{ + gtk_widget_set_visible (view->details->stop, enabled); +} + +static void +nautilus_files_view_parent_set (GtkWidget *widget, + GtkWidget *old_parent) +{ + NautilusWindow *window; + NautilusFilesView *view; + GtkWidget *parent; + + view = NAUTILUS_FILES_VIEW (widget); + + parent = gtk_widget_get_parent (widget); + window = nautilus_files_view_get_window (view); + g_assert (parent == NULL || old_parent == NULL); + + if (GTK_WIDGET_CLASS (nautilus_files_view_parent_class)->parent_set != NULL) { + GTK_WIDGET_CLASS (nautilus_files_view_parent_class)->parent_set (widget, old_parent); + } + + if (view->details->stop_signal_handler > 0) { + g_signal_handler_disconnect (window, view->details->stop_signal_handler); + view->details->stop_signal_handler = 0; + } + + if (view->details->reload_signal_handler > 0) { + g_signal_handler_disconnect (window, view->details->reload_signal_handler); + view->details->reload_signal_handler = 0; + } + + if (parent != NULL) { + g_assert (old_parent == NULL); + + if (view->details->slot == nautilus_window_get_active_slot (window)) { + view->details->active = TRUE; + gtk_widget_insert_action_group (GTK_WIDGET (nautilus_files_view_get_window (view)), + "view", + G_ACTION_GROUP (view->details->view_action_group)); + } + + view->details->stop_signal_handler = + g_signal_connect (window, + "action-enabled-changed::stop", + G_CALLBACK (action_stop_enabled_changed), + view); + view->details->reload_signal_handler = + g_signal_connect (window, + "action-enabled-changed::reload", + G_CALLBACK (action_reload_enabled_changed), + view); + } else { + remove_update_context_menus_timeout_callback (view); + gtk_widget_insert_action_group (GTK_WIDGET (nautilus_files_view_get_window (view)), + "view", + NULL); + } +} + +static gboolean +nautilus_files_view_key_press_event (GtkWidget *widget, + GdkEventKey *event) +{ + NautilusFilesView *view; + gint i; + + view = NAUTILUS_FILES_VIEW (widget); + + for (i = 0; i < G_N_ELEMENTS (extra_view_keybindings); i++) { + if (extra_view_keybindings[i].keyval == event->keyval) { + GAction *action; + + action = g_action_map_lookup_action (G_ACTION_MAP (view->details->view_action_group), + extra_view_keybindings[i].action); + + if (g_action_get_enabled (action)) { + g_action_activate (action, NULL); + return GDK_EVENT_STOP; + } + + break; + } + } + + return GDK_EVENT_PROPAGATE; +} + +static void +nautilus_files_view_class_init (NautilusFilesViewClass *klass) +{ + GObjectClass *oclass; + GtkWidgetClass *widget_class; + + widget_class = GTK_WIDGET_CLASS (klass); + oclass = G_OBJECT_CLASS (klass); + + oclass->finalize = nautilus_files_view_finalize; + oclass->get_property = nautilus_files_view_get_property; + oclass->set_property = nautilus_files_view_set_property; + + widget_class->destroy = nautilus_files_view_destroy; + widget_class->key_press_event = nautilus_files_view_key_press_event; + widget_class->scroll_event = nautilus_files_view_scroll_event; + widget_class->parent_set = nautilus_files_view_parent_set; + widget_class->grab_focus = nautilus_files_view_grab_focus; + + g_type_class_add_private (klass, sizeof (NautilusFilesViewDetails)); + + signals[ADD_FILE] = + g_signal_new ("add-file", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NautilusFilesViewClass, add_file), + NULL, NULL, + g_cclosure_marshal_generic, + G_TYPE_NONE, 2, NAUTILUS_TYPE_FILE, NAUTILUS_TYPE_DIRECTORY); + signals[BEGIN_FILE_CHANGES] = + g_signal_new ("begin-file-changes", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NautilusFilesViewClass, begin_file_changes), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + signals[BEGIN_LOADING] = + g_signal_new ("begin-loading", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NautilusFilesViewClass, begin_loading), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + signals[CLEAR] = + g_signal_new ("clear", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NautilusFilesViewClass, clear), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + signals[END_FILE_CHANGES] = + g_signal_new ("end-file-changes", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NautilusFilesViewClass, end_file_changes), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + signals[END_LOADING] = + g_signal_new ("end-loading", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NautilusFilesViewClass, end_loading), + NULL, NULL, + g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + signals[FILE_CHANGED] = + g_signal_new ("file-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NautilusFilesViewClass, file_changed), + NULL, NULL, + g_cclosure_marshal_generic, + G_TYPE_NONE, 2, NAUTILUS_TYPE_FILE, NAUTILUS_TYPE_DIRECTORY); + signals[REMOVE_FILE] = + g_signal_new ("remove-file", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (NautilusFilesViewClass, remove_file), + NULL, NULL, + g_cclosure_marshal_generic, + G_TYPE_NONE, 2, NAUTILUS_TYPE_FILE, NAUTILUS_TYPE_DIRECTORY); + signals[SELECTION_CHANGED] = + g_signal_new ("selection-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + klass->get_selected_icon_locations = real_get_selected_icon_locations; + klass->is_read_only = real_is_read_only; + klass->can_rename_file = can_rename_file; + klass->get_backing_uri = real_get_backing_uri; + klass->using_manual_layout = real_using_manual_layout; + klass->get_window = nautilus_files_view_get_window; + klass->update_context_menus = real_update_context_menus; + klass->update_actions_state = real_update_actions_state; + + copied_files_atom = gdk_atom_intern ("x-special/gnome-copied-files", FALSE); + + properties[PROP_WINDOW_SLOT] = + g_param_spec_object ("window-slot", + "Window Slot", + "The parent window slot reference", + NAUTILUS_TYPE_WINDOW_SLOT, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY); + properties[PROP_SUPPORTS_ZOOMING] = + g_param_spec_boolean ("supports-zooming", + "Supports zooming", + "Whether the view supports zooming", + TRUE, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + properties[PROP_ICON] = + g_param_spec_object ("icon", + "Icon", + "The icon that represents the view", + G_TYPE_ICON, + G_PARAM_READABLE); + + properties[PROP_VIEW_WIDGET] = + g_param_spec_object ("view-widget", + "View widget", + "The view's widget that will appear under the view menu button", + GTK_TYPE_WIDGET, + G_PARAM_READABLE); + + g_object_class_install_properties (oclass, NUM_PROPERTIES, properties); +} + +static void +nautilus_files_view_init (NautilusFilesView *view) +{ + GtkBuilder *builder; + AtkObject *atk_object; + NautilusDirectory *scripts_directory; + NautilusDirectory *templates_directory; + gchar *templates_uri; + GApplication *app; + const gchar *open_accels[] = { + "<control>o", + "<alt>Down", + NULL + }; + + nautilus_profile_start (NULL); + + view->details = G_TYPE_INSTANCE_GET_PRIVATE (view, NAUTILUS_TYPE_FILES_VIEW, + NautilusFilesViewDetails); + + /* NautilusFloatingBar listen to its parent's 'enter-notify-event' signal + * and GtkOverlay doesn't have it enabled by default, so we have to add them + * here. + */ + gtk_widget_add_events (GTK_WIDGET (view), + GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); + + /* View menu */ + builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/nautilus-toolbar-view-menu.xml"); + view->details->view_menu_widget = g_object_ref (gtk_builder_get_object (builder, "view_menu_widget")); + view->details->zoom_level_scale = GTK_WIDGET (gtk_builder_get_object (builder, "zoom_level_scale")); + view->details->zoom_adjustment = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "zoom_adjustment")); + + view->details->sort_menu = GTK_WIDGET (gtk_builder_get_object (builder, "sort_menu")); + view->details->sort_trash_time = GTK_WIDGET (gtk_builder_get_object (builder, "sort_trash_time")); + view->details->sort_search_relevance = GTK_WIDGET (gtk_builder_get_object (builder, "sort_search_relevance")); + view->details->visible_columns = GTK_WIDGET (gtk_builder_get_object (builder, "visible_columns")); + view->details->reload = GTK_WIDGET (gtk_builder_get_object (builder, "reload")); + view->details->stop = GTK_WIDGET (gtk_builder_get_object (builder, "stop")); + + g_signal_connect (view->details->zoom_level_scale, "value-changed", + G_CALLBACK (zoom_level_changed), view); + + g_object_unref (builder); + + /* Scrolled Window */ + view->details->scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (view->details->scrolled_window), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_widget_show (view->details->scrolled_window); + + g_signal_connect_swapped (view->details->scrolled_window, + "scroll-event", + G_CALLBACK (nautilus_files_view_scroll_event), + view); + + gtk_container_add (GTK_CONTAINER (view), view->details->scrolled_window); + + /* Empty states */ + builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/nautilus-no-search-results.ui"); + view->details->no_search_results_widget = GTK_WIDGET (gtk_builder_get_object (builder, "no_search_results")); + gtk_overlay_add_overlay (GTK_OVERLAY (view), view->details->no_search_results_widget); + g_object_unref (builder); + + builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/nautilus-folder-is-empty.ui"); + view->details->folder_is_empty_widget = GTK_WIDGET (gtk_builder_get_object (builder, "folder_is_empty")); + gtk_overlay_add_overlay (GTK_OVERLAY (view), view->details->folder_is_empty_widget); + g_object_unref (builder); + + /* Floating bar */ + view->details->floating_bar = nautilus_floating_bar_new (NULL, NULL, FALSE); + gtk_widget_set_halign (view->details->floating_bar, GTK_ALIGN_END); + gtk_widget_set_valign (view->details->floating_bar, GTK_ALIGN_END); + gtk_overlay_add_overlay (GTK_OVERLAY (view), view->details->floating_bar); + + g_signal_connect (view->details->floating_bar, + "action", + G_CALLBACK (floating_bar_action_cb), + view); + + /* 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_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_files_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)); + + 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); + + /* 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.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 */ + gtk_application_set_accels_for_action (GTK_APPLICATION (app), + "view.open-with-default-application", open_accels); + 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", "Delete"); + nautilus_application_add_accelerator (app, "view.delete-from-trash", "Delete"); + nautilus_application_add_accelerator (app, "view.delete-permanently-shortcut", "<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.new-folder", "<control><shift>n"); + /* 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"); + + /* Show a warning dialog to inform the user that the shorcut for move to trash + * changed */ + nautilus_application_add_accelerator (app, "view.show-move-to-trash-shortcut-changed-dialog", "<control>Delete"); + + nautilus_profile_end (NULL); +} + +NautilusFilesView * +nautilus_files_view_new (const gchar *id, + NautilusWindowSlot *slot) +{ + NautilusFilesView *view = NULL; + + if (g_strcmp0 (id, NAUTILUS_CANVAS_VIEW_ID) == 0) { + view = nautilus_canvas_view_new (slot); + } else if (g_strcmp0 (id, NAUTILUS_LIST_VIEW_ID) == 0) { + view = nautilus_list_view_new (slot); + } else if (g_strcmp0 (id, NAUTILUS_DESKTOP_CANVAS_VIEW_ID) == 0) { + view = nautilus_desktop_canvas_view_new (slot); + } +#if ENABLE_EMPTY_VIEW + else if (g_strcmp0 (id, NAUTILUS_EMPTY_VIEW_ID) == 0) { + view = nautilus_empty_view_new (slot); + } +#endif + + if (view == NULL) { + g_critical ("Unknown view type ID: %s", id); + } else if (g_object_is_floating (view)) { + g_object_ref_sink (view); + } + + return view; +} diff --git a/src/nautilus-files-view.h b/src/nautilus-files-view.h new file mode 100644 index 000000000..606a054c6 --- /dev/null +++ b/src/nautilus-files-view.h @@ -0,0 +1,401 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* nautilus-view.h + * + * Copyright (C) 1999, 2000 Free Software Foundaton + * Copyright (C) 2000, 2001 Eazel, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + * + * Authors: Ettore Perazzoli + * Darin Adler <darin@bentspoon.com> + * John Sullivan <sullivan@eazel.com> + * Pavel Cisler <pavel@eazel.com> + */ + +#ifndef NAUTILUS_FILES_VIEW_H +#define NAUTILUS_FILES_VIEW_H + +#include <gtk/gtk.h> +#include <gio/gio.h> + +#include <libnautilus-private/nautilus-directory.h> +#include <libnautilus-private/nautilus-file.h> +#include <libnautilus-private/nautilus-link.h> + +typedef struct NautilusFilesView NautilusFilesView; +typedef struct NautilusFilesViewClass NautilusFilesViewClass; + +#include "nautilus-window.h" +#include "nautilus-window-slot.h" + +#if ENABLE_EMPTY_VIEW +#define NAUTILUS_EMPTY_VIEW_ID "OAFIID:Nautilus_File_Manager_Empty_View" +#endif + +#define NAUTILUS_CANVAS_VIEW_ID "OAFIID:Nautilus_File_Manager_Canvas_View" +#define NAUTILUS_DESKTOP_CANVAS_VIEW_ID "OAFIID:Nautilus_File_Manager_Desktop_Canvas_View" +#define NAUTILUS_LIST_VIEW_ID "OAFIID:Nautilus_File_Manager_List_View" + +#define NAUTILUS_TYPE_FILES_VIEW nautilus_files_view_get_type() +#define NAUTILUS_FILES_VIEW(obj)\ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_FILES_VIEW, NautilusFilesView)) +#define NAUTILUS_FILES_VIEW_CLASS(klass)\ + (G_TYPE_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_FILES_VIEW, NautilusFilesViewClass)) +#define NAUTILUS_IS_FILES_VIEW(obj)\ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NAUTILUS_TYPE_FILES_VIEW)) +#define NAUTILUS_IS_FILES_VIEW_CLASS(klass)\ + (G_TYPE_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_FILES_VIEW)) +#define NAUTILUS_FILES_VIEW_GET_CLASS(obj)\ + (G_TYPE_INSTANCE_GET_CLASS ((obj), NAUTILUS_TYPE_FILES_VIEW, NautilusFilesViewClass)) + +typedef struct NautilusFilesViewDetails NautilusFilesViewDetails; + +struct NautilusFilesView { + GtkOverlay parent; + + NautilusFilesViewDetails *details; +}; + +struct NautilusFilesViewClass { + GtkOverlayClass parent_class; + + /* The 'clear' signal is emitted to empty the view of its contents. + * It must be replaced by each subclass. + */ + void (* clear) (NautilusFilesView *view); + + /* The 'begin_file_changes' signal is emitted before a set of files + * are added to the view. It can be replaced by a subclass to do any + * necessary preparation for a set of new files. The default + * implementation does nothing. + */ + void (* begin_file_changes) (NautilusFilesView *view); + + /* The 'add_file' signal is emitted to add one file to the view. + * It must be replaced by each subclass. + */ + void (* add_file) (NautilusFilesView *view, + NautilusFile *file, + NautilusDirectory *directory); + void (* remove_file) (NautilusFilesView *view, + NautilusFile *file, + NautilusDirectory *directory); + + /* The 'file_changed' signal is emitted to signal a change in a file, + * including the file being removed. + * It must be replaced by each subclass. + */ + void (* file_changed) (NautilusFilesView *view, + NautilusFile *file, + NautilusDirectory *directory); + + /* The 'end_file_changes' signal is emitted after a set of files + * are added to the view. It can be replaced by a subclass to do any + * necessary cleanup (typically, cleanup for code in begin_file_changes). + * The default implementation does nothing. + */ + void (* end_file_changes) (NautilusFilesView *view); + + /* The 'begin_loading' signal is emitted before any of the contents + * of a directory are added to the view. It can be replaced by a + * subclass to do any necessary preparation to start dealing with a + * new directory. The default implementation does nothing. + */ + void (* begin_loading) (NautilusFilesView *view); + + /* The 'end_loading' signal is emitted after all of the contents + * of a directory are added to the view. It can be replaced by a + * subclass to do any necessary clean-up. The default implementation + * does nothing. + * + * If all_files_seen is true, the handler may assume that + * no load error ocurred, and all files of the underlying + * directory were loaded. + * + * Otherwise, end_loading was emitted due to cancellation, + * which usually means that not all files are available. + */ + void (* end_loading) (NautilusFilesView *view, + gboolean all_files_seen); + + /* Function pointers that don't have corresponding signals */ + + /* get_backing uri is a function pointer for subclasses to + * override. Subclasses may replace it with a function that + * returns the URI for the location where to create new folders, + * files, links and paste the clipboard to. + */ + + char * (* get_backing_uri) (NautilusFilesView *view); + + /* get_selection is not a signal; it is just a function pointer for + * subclasses to replace (override). Subclasses must replace it + * with a function that returns a newly-allocated GList of + * NautilusFile pointers. + */ + GList * (* get_selection) (NautilusFilesView *view); + + /* get_selection_for_file_transfer is a function pointer for + * subclasses to replace (override). Subclasses must replace it + * with a function that returns a newly-allocated GList of + * NautilusFile pointers. The difference from get_selection is + * that any files in the selection that also has a parent folder + * in the selection is not included. + */ + GList * (* get_selection_for_file_transfer)(NautilusFilesView *view); + + /* select_all is a function pointer that subclasses must override to + * select all of the items in the view */ + void (* select_all) (NautilusFilesView *view); + + /* select_first is a function pointer that subclasses must override to + * select the first item in the view */ + void (* select_first) (NautilusFilesView *view); + + /* set_selection is a function pointer that subclasses must + * override to select the specified items (and unselect all + * others). The argument is a list of NautilusFiles. */ + + void (* set_selection) (NautilusFilesView *view, + GList *selection); + + /* invert_selection is a function pointer that subclasses must + * override to invert selection. */ + + void (* invert_selection) (NautilusFilesView *view); + + /* Return an array of locations of selected icons in their view. */ + GArray * (* get_selected_icon_locations) (NautilusFilesView *view); + + /* bump_zoom_level is a function pointer that subclasses must override + * to change the zoom level of an object. */ + void (* bump_zoom_level) (NautilusFilesView *view, + int zoom_increment); + + /* restore_default_zoom_level is a function pointer that subclasses must override + * to restore the zoom level of an object to a default setting. */ + void (* restore_default_zoom_level) (NautilusFilesView *view); + + /* can_zoom_in is a function pointer that subclasses must override to + * return whether the view is at maximum size (furthest-in zoom level) */ + gboolean (* can_zoom_in) (NautilusFilesView *view); + + /* can_zoom_out is a function pointer that subclasses must override to + * return whether the view is at minimum size (furthest-out zoom level) */ + gboolean (* can_zoom_out) (NautilusFilesView *view); + + /* reveal_selection is a function pointer that subclasses may + * override to make sure the selected items are sufficiently + * apparent to the user (e.g., scrolled into view). By default, + * this does nothing. + */ + void (* reveal_selection) (NautilusFilesView *view); + + /* merge_menus is a function pointer that subclasses can override to + * add their own menu items to the window's menu bar. + * If overridden, subclasses must call parent class's function. + */ + void (* merge_menus) (NautilusFilesView *view); + void (* unmerge_menus) (NautilusFilesView *view); + + /* update_menus is a function pointer that subclasses can override to + * update the sensitivity or wording of menu items in the menu bar. + * It is called (at least) whenever the selection changes. If overridden, + * subclasses must call parent class's function. + */ + void (* update_context_menus) (NautilusFilesView *view); + + void (* update_actions_state) (NautilusFilesView *view); + + /* sort_files is a function pointer that subclasses can override + * to provide a sorting order to determine which files should be + * presented when only a partial list is provided. + */ + int (* compare_files) (NautilusFilesView *view, + NautilusFile *a, + NautilusFile *b); + + /* using_manual_layout is a function pointer that subclasses may + * override to control whether or not items can be freely positioned + * on the user-visible area. + * Note that this value is not guaranteed to be constant within the + * view's lifecycle. */ + gboolean (* using_manual_layout) (NautilusFilesView *view); + + /* is_read_only is a function pointer that subclasses may + * override to control whether or not the user is allowed to + * change the contents of the currently viewed directory. The + * default implementation checks the permissions of the + * directory. + */ + gboolean (* is_read_only) (NautilusFilesView *view); + + /* is_empty is a function pointer that subclasses must + * override to report whether the view contains any items. + */ + gboolean (* is_empty) (NautilusFilesView *view); + + gboolean (* can_rename_file) (NautilusFilesView *view, + NautilusFile *file); + + /* convert *point from widget's coordinate system to a coordinate + * system used for specifying file operation positions, which is view-specific. + * + * This is used by the the icon view, which converts the screen position to a zoom + * level-independent coordinate system. + */ + void (* widget_to_file_operation_position) (NautilusFilesView *view, + GdkPoint *position); + + /* Preference change callbacks, overriden by icon and list views. + * Icon and list views respond by synchronizing to the new preference + * values and forcing an update if appropriate. + */ + void (* click_policy_changed) (NautilusFilesView *view); + void (* sort_directories_first_changed) (NautilusFilesView *view); + + /* Get the id string for this view. Its a constant string, not memory managed */ + const char * (* get_view_id) (NautilusFilesView *view); + + /* Return the uri of the first visible file */ + char * (* get_first_visible_file) (NautilusFilesView *view); + /* Scroll the view so that the file specified by the uri is at the top + of the view */ + void (* scroll_to_file) (NautilusFilesView *view, + const char *uri); + + NautilusWindow * (*get_window) (NautilusFilesView *view); + + GdkRectangle * (*compute_rename_popover_relative_to) (NautilusFilesView *view); + + GIcon * (* get_icon) (NautilusFilesView *view); +}; + +/* GObject support */ +GType nautilus_files_view_get_type (void); + +NautilusFilesView * nautilus_files_view_new (const gchar *id, + NautilusWindowSlot *slot); + +/* Functions callable from the user interface and elsewhere. */ +NautilusWindowSlot *nautilus_files_view_get_nautilus_window_slot (NautilusFilesView *view); +char * nautilus_files_view_get_uri (NautilusFilesView *view); + +void nautilus_files_view_display_selection_info (NautilusFilesView *view); + +GdkAtom nautilus_files_view_get_copied_files_atom (NautilusFilesView *view); + +/* Wrappers for signal emitters. These are normally called + * only by NautilusFilesView itself. They have corresponding signals + * that observers might want to connect with. + */ +gboolean nautilus_files_view_get_loading (NautilusFilesView *view); + +/* Hooks for subclasses to call. These are normally called only by + * NautilusFilesView and its subclasses + */ +void nautilus_files_view_activate_files (NautilusFilesView *view, + GList *files, + NautilusWindowOpenFlags flags, + gboolean confirm_multiple); +void nautilus_files_view_preview_files (NautilusFilesView *view, + GList *files, + GArray *locations); +void nautilus_files_view_start_batching_selection_changes (NautilusFilesView *view); +void nautilus_files_view_stop_batching_selection_changes (NautilusFilesView *view); +void nautilus_files_view_notify_selection_changed (NautilusFilesView *view); +NautilusDirectory *nautilus_files_view_get_model (NautilusFilesView *view); +NautilusFile *nautilus_files_view_get_directory_as_file (NautilusFilesView *view); +void nautilus_files_view_pop_up_background_context_menu (NautilusFilesView *view, + GdkEventButton *event); +void nautilus_files_view_pop_up_selection_context_menu (NautilusFilesView *view, + GdkEventButton *event); +gboolean nautilus_files_view_should_show_file (NautilusFilesView *view, + NautilusFile *file); +gboolean nautilus_files_view_should_sort_directories_first (NautilusFilesView *view); +void nautilus_files_view_ignore_hidden_file_preferences (NautilusFilesView *view); +void nautilus_files_view_set_show_foreign (NautilusFilesView *view, + gboolean show_foreign); +gboolean nautilus_files_view_handle_scroll_event (NautilusFilesView *view, + GdkEventScroll *event); + +void nautilus_files_view_add_subdirectory (NautilusFilesView *view, + NautilusDirectory *directory); +void nautilus_files_view_remove_subdirectory (NautilusFilesView *view, + NautilusDirectory *directory); + +gboolean nautilus_files_view_is_editable (NautilusFilesView *view); +NautilusWindow * nautilus_files_view_get_window (NautilusFilesView *view); + +/* NautilusFilesView methods */ +const char * nautilus_files_view_get_view_id (NautilusFilesView *view); + +/* file operations */ +char * nautilus_files_view_get_backing_uri (NautilusFilesView *view); +void nautilus_files_view_move_copy_items (NautilusFilesView *view, + const GList *item_uris, + GArray *relative_item_points, + const char *target_uri, + int copy_action, + int x, + int y); +void nautilus_files_view_new_file_with_initial_contents (NautilusFilesView *view, + const char *parent_uri, + const char *filename, + const char *initial_contents, + int length, + GdkPoint *pos); + +/* selection handling */ +void nautilus_files_view_activate_selection (NautilusFilesView *view); +int nautilus_files_view_get_selection_count (NautilusFilesView *view); +GList * nautilus_files_view_get_selection (NautilusFilesView *view); +void nautilus_files_view_set_selection (NautilusFilesView *view, + GList *selection); + + +void nautilus_files_view_load_location (NautilusFilesView *view, + GFile *location); +void nautilus_files_view_stop_loading (NautilusFilesView *view); + +char * nautilus_files_view_get_first_visible_file (NautilusFilesView *view); +void nautilus_files_view_scroll_to_file (NautilusFilesView *view, + const char *uri); +char * nautilus_files_view_get_title (NautilusFilesView *view); +gboolean nautilus_files_view_supports_zooming (NautilusFilesView *view); +void nautilus_files_view_bump_zoom_level (NautilusFilesView *view, + int zoom_increment); +void nautilus_files_view_zoom_to_level (NautilusFilesView *view, + gint level); +void nautilus_files_view_restore_default_zoom_level (NautilusFilesView *view); +gboolean nautilus_files_view_can_zoom_in (NautilusFilesView *view); +gboolean nautilus_files_view_can_zoom_out (NautilusFilesView *view); +void nautilus_files_view_update_menus (NautilusFilesView *view); + +void nautilus_files_view_update_context_menus (NautilusFilesView *view); +void nautilus_files_view_update_toolbar_menus (NautilusFilesView *view); +void nautilus_files_view_update_actions_state (NautilusFilesView *view); + +void nautilus_files_view_action_show_hidden_files (NautilusFilesView *view, + gboolean show_hidden); + +GActionGroup * nautilus_files_view_get_action_group (NautilusFilesView *view); +GtkWidget* nautilus_files_view_get_content_widget (NautilusFilesView *view); +gboolean nautilus_files_view_is_search (NautilusFilesView *view); + +GIcon* nautilus_files_view_get_icon (NautilusFilesView *view); + +GtkWidget* nautilus_files_view_get_view_widget (NautilusFilesView *view); + +#endif /* NAUTILUS_FILES_VIEW_H */ diff --git a/src/nautilus-list-view.c b/src/nautilus-list-view.c index 3beff6626..195a6e3aa 100644 --- a/src/nautilus-list-view.c +++ b/src/nautilus-list-view.c @@ -29,7 +29,7 @@ #include "nautilus-list-model.h" #include "nautilus-error-reporting.h" -#include "nautilus-view-dnd.h" +#include "nautilus-files-view-dnd.h" #include "nautilus-toolbar.h" #include <string.h> @@ -126,8 +126,8 @@ static GdkCursor * hand_cursor = NULL; 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 GList *nautilus_list_view_get_selection (NautilusFilesView *view); +static GList *nautilus_list_view_get_selection_for_file_transfer (NautilusFilesView *view); static void nautilus_list_view_set_zoom_level (NautilusListView *view, NautilusListZoomLevel new_level); static void nautilus_list_view_scroll_to_file (NautilusListView *view, @@ -142,7 +142,7 @@ static char **get_column_order (NautilusListVi static char **get_default_column_order (NautilusListView *list_view); -G_DEFINE_TYPE (NautilusListView, nautilus_list_view, NAUTILUS_TYPE_VIEW); +G_DEFINE_TYPE (NautilusListView, nautilus_list_view, NAUTILUS_TYPE_FILES_VIEW); static const char * default_search_visible_columns[] = { "name", "size", "where", NULL @@ -195,11 +195,11 @@ get_default_sort_order (NautilusFile *file, gboolean *reversed) static void list_selection_changed_callback (GtkTreeSelection *selection, gpointer user_data) { - NautilusView *view; + NautilusFilesView *view; - view = NAUTILUS_VIEW (user_data); + view = NAUTILUS_FILES_VIEW (user_data); - nautilus_view_notify_selection_changed (view); + nautilus_files_view_notify_selection_changed (view); } /* Move these to eel? */ @@ -236,10 +236,10 @@ preview_selected_items (NautilusListView *view) { GList *file_list; - file_list = nautilus_list_view_get_selection (NAUTILUS_VIEW (view)); + file_list = nautilus_list_view_get_selection (NAUTILUS_FILES_VIEW (view)); if (file_list != NULL) { - nautilus_view_preview_files (NAUTILUS_VIEW (view), + nautilus_files_view_preview_files (NAUTILUS_FILES_VIEW (view), file_list, NULL); nautilus_file_list_free (file_list); } @@ -250,8 +250,8 @@ activate_selected_items (NautilusListView *view) { GList *file_list; - file_list = nautilus_list_view_get_selection (NAUTILUS_VIEW (view)); - nautilus_view_activate_files (NAUTILUS_VIEW (view), + file_list = nautilus_list_view_get_selection (NAUTILUS_FILES_VIEW (view)); + nautilus_files_view_activate_files (NAUTILUS_FILES_VIEW (view), file_list, 0, TRUE); nautilus_file_list_free (file_list); @@ -278,9 +278,9 @@ activate_selected_items_alternate (NautilusListView *view, nautilus_file_ref (file); file_list = g_list_prepend (NULL, file); } else { - file_list = nautilus_list_view_get_selection (NAUTILUS_VIEW (view)); + file_list = nautilus_list_view_get_selection (NAUTILUS_FILES_VIEW (view)); } - nautilus_view_activate_files (NAUTILUS_VIEW (view), + nautilus_files_view_activate_files (NAUTILUS_FILES_VIEW (view), file_list, flags, TRUE); @@ -612,9 +612,9 @@ static void do_popup_menu (GtkWidget *widget, NautilusListView *view, GdkEventButton *event) { if (tree_view_has_selection (GTK_TREE_VIEW (widget))) { - nautilus_view_pop_up_selection_context_menu (NAUTILUS_VIEW (view), event); + nautilus_files_view_pop_up_selection_context_menu (NAUTILUS_FILES_VIEW (view), event); } else { - nautilus_view_pop_up_background_context_menu (NAUTILUS_VIEW (view), event); + nautilus_files_view_pop_up_background_context_menu (NAUTILUS_FILES_VIEW (view), event); } } @@ -888,7 +888,7 @@ row_expanded_callback (GtkTreeView *treeview, DEBUG ("Row expaded callback for uri %s", uri); g_free (uri); - nautilus_view_add_subdirectory (NAUTILUS_VIEW (view), directory); + nautilus_files_view_add_subdirectory (NAUTILUS_FILES_VIEW (view), directory); if (nautilus_directory_are_all_files_seen (directory)) { nautilus_list_model_subdirectory_done_loading (view->details->model, @@ -1026,13 +1026,13 @@ subdirectory_unloaded_callback (NautilusListModel *model, g_signal_handlers_disconnect_by_func (directory, G_CALLBACK (subdirectory_done_loading_callback), view); - nautilus_view_remove_subdirectory (NAUTILUS_VIEW (view), directory); + nautilus_files_view_remove_subdirectory (NAUTILUS_FILES_VIEW (view), directory); } static gboolean key_press_callback (GtkWidget *widget, GdkEventKey *event, gpointer callback_data) { - NautilusView *view; + NautilusFilesView *view; GdkEventButton button_event = { 0 }; gboolean handled; GtkTreeView *tree_view; @@ -1040,13 +1040,13 @@ key_press_callback (GtkWidget *widget, GdkEventKey *event, gpointer callback_dat tree_view = GTK_TREE_VIEW (widget); - view = NAUTILUS_VIEW (callback_data); + view = NAUTILUS_FILES_VIEW (callback_data); handled = FALSE; switch (event->keyval) { case GDK_KEY_F10: if (event->state & GDK_CONTROL_MASK) { - nautilus_view_pop_up_background_context_menu (view, &button_event); + nautilus_files_view_pop_up_background_context_menu (view, &button_event); handled = TRUE; } break; @@ -1124,13 +1124,13 @@ test_expand_row_callback (GtkTreeView *tree_view, } static void -nautilus_list_view_reveal_selection (NautilusView *view) +nautilus_list_view_reveal_selection (NautilusFilesView *view) { GList *selection; g_return_if_fail (NAUTILUS_IS_LIST_VIEW (view)); - selection = nautilus_view_get_selection (view); + selection = nautilus_files_view_get_selection (view); /* Make sure at least one of the selected items is scrolled into view */ if (selection != NULL) { @@ -1188,7 +1188,7 @@ sort_column_changed_callback (GtkTreeSortable *sortable, char *reversed_attr, *default_reversed_attr; gboolean default_sort_reversed; - file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (view)); + file = nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (view)); gtk_tree_sortable_get_sort_column_id (sortable, &sort_column_id, &reversed); sort_attr = nautilus_list_model_get_attribute_from_sort_column_id (view->details->model, sort_column_id); @@ -1229,7 +1229,7 @@ sort_column_changed_callback (GtkTreeSortable *sortable, default_reversed_attr, reversed_attr); /* Make sure selected item(s) is visible after sort */ - nautilus_list_view_reveal_selection (NAUTILUS_VIEW (view)); + nautilus_list_view_reveal_selection (NAUTILUS_FILES_VIEW (view)); view->details->last_sort_attr = sort_attr; } @@ -1242,7 +1242,7 @@ get_root_uri_callback (NautilusTreeViewDragDest *dest, view = NAUTILUS_LIST_VIEW (user_data); - return nautilus_view_get_uri (NAUTILUS_VIEW (view)); + return nautilus_files_view_get_uri (NAUTILUS_FILES_VIEW (view)); } static NautilusFile * @@ -1262,7 +1262,7 @@ static void list_view_handle_netscape_url (NautilusTreeViewDragDest *dest, const char *encoded_url, const char *target_uri, GdkDragAction action, int x, int y, NautilusListView *view) { - nautilus_view_handle_netscape_url_drop (NAUTILUS_VIEW (view), + nautilus_files_view_handle_netscape_url_drop (NAUTILUS_FILES_VIEW (view), encoded_url, target_uri, action, x, y); } @@ -1271,7 +1271,7 @@ list_view_handle_uri_list (NautilusTreeViewDragDest *dest, const char *item_uris const char *target_uri, GdkDragAction action, int x, int y, NautilusListView *view) { - nautilus_view_handle_uri_list_drop (NAUTILUS_VIEW (view), + nautilus_files_view_handle_uri_list_drop (NAUTILUS_FILES_VIEW (view), item_uris, target_uri, action, x, y); } @@ -1280,7 +1280,7 @@ list_view_handle_text (NautilusTreeViewDragDest *dest, const char *text, const char *target_uri, GdkDragAction action, int x, int y, NautilusListView *view) { - nautilus_view_handle_text_drop (NAUTILUS_VIEW (view), + nautilus_files_view_handle_text_drop (NAUTILUS_FILES_VIEW (view), text, target_uri, action, x, y); } @@ -1289,7 +1289,7 @@ list_view_handle_raw (NautilusTreeViewDragDest *dest, const char *raw_data, int length, const char *target_uri, const char *direct_save_uri, GdkDragAction action, int x, int y, NautilusListView *view) { - nautilus_view_handle_raw_drop (NAUTILUS_VIEW (view), + nautilus_files_view_handle_raw_drop (NAUTILUS_FILES_VIEW (view), raw_data, length, target_uri, direct_save_uri, action, x, y); } @@ -1299,7 +1299,7 @@ list_view_handle_hover (NautilusTreeViewDragDest *dest, const char *target_uri, NautilusListView *view) { - nautilus_view_handle_hover (NAUTILUS_VIEW (view), target_uri); + nautilus_files_view_handle_hover (NAUTILUS_FILES_VIEW (view), target_uri); } static void @@ -1312,12 +1312,12 @@ move_copy_items_callback (NautilusTreeViewDragDest *dest, gpointer user_data) { - NautilusView *view = user_data; + NautilusFilesView *view = user_data; nautilus_clipboard_clear_if_colliding_uris (GTK_WIDGET (view), item_uris, - nautilus_view_get_copied_files_atom (view)); - nautilus_view_move_copy_items (view, + nautilus_files_view_get_copied_files_atom (view)); + nautilus_files_view_move_copy_items (view, item_uris, NULL, target_uri, @@ -1337,7 +1337,7 @@ column_header_menu_toggled (GtkCheckMenuItem *menu_item, GList *l; int i; - file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (list_view)); + file = nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (list_view)); visible_columns = get_visible_columns (list_view); column_order = get_column_order (list_view); column = g_object_get_data (G_OBJECT (menu_item), "column-name"); @@ -1383,7 +1383,7 @@ column_header_menu_use_default (GtkMenuItem *menu_item, char **default_columns; char **default_order; - file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (list_view)); + file = nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (list_view)); nautilus_file_set_metadata_list (file, NAUTILUS_METADATA_KEY_LIST_VIEW_COLUMN_ORDER, NULL); nautilus_file_set_metadata_list (file, NAUTILUS_METADATA_KEY_LIST_VIEW_VISIBLE_COLUMNS, NULL); @@ -1419,7 +1419,7 @@ column_header_clicked (GtkWidget *column_button, return FALSE; } - file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (list_view)); + file = nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (list_view)); visible_columns = get_visible_columns (list_view); column_order = get_column_order (list_view); @@ -1518,7 +1518,7 @@ apply_columns_settings (NautilusListView *list_view, GList *l; int i; - file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (list_view)); + file = nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (list_view)); /* prepare ordered list of view columns using column_order and visible_columns */ view_columns = NULL; @@ -1641,7 +1641,7 @@ location_cell_data_func (GtkTreeViewColumn *column, GFile *base_location; gchar *where = NULL; - directory = nautilus_view_get_model (NAUTILUS_VIEW (view)); + directory = nautilus_files_view_get_model (NAUTILUS_FILES_VIEW (view)); home_location = g_file_new_for_path (g_get_home_dir ()); @@ -1803,7 +1803,7 @@ create_and_set_up_tree_view (NautilusListView *view) gchar **default_column_order, **default_visible_columns; GtkWidget *content_widget; - content_widget = nautilus_view_get_content_widget (NAUTILUS_VIEW (view)); + content_widget = nautilus_files_view_get_content_widget (NAUTILUS_FILES_VIEW (view)); view->details->tree_view = GTK_TREE_VIEW (gtk_tree_view_new ()); view->details->columns = g_hash_table_new_full (g_str_hash, g_str_equal, @@ -2045,7 +2045,7 @@ create_and_set_up_tree_view (NautilusListView *view) } static void -nautilus_list_view_add_file (NautilusView *view, NautilusFile *file, NautilusDirectory *directory) +nautilus_list_view_add_file (NautilusFilesView *view, NautilusFile *file, NautilusDirectory *directory) { NautilusListModel *model; @@ -2059,13 +2059,13 @@ get_default_visible_columns (NautilusListView *list_view) NautilusFile *file; NautilusDirectory *directory; - file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (list_view)); + file = nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (list_view)); if (nautilus_file_is_in_trash (file)) { return g_strdupv ((gchar **) default_trash_visible_columns); } - directory = nautilus_view_get_model (NAUTILUS_VIEW (list_view)); + directory = nautilus_files_view_get_model (NAUTILUS_FILES_VIEW (list_view)); if (NAUTILUS_IS_SEARCH_DIRECTORY (directory)) { return g_strdupv ((gchar **) default_search_visible_columns); } @@ -2080,7 +2080,7 @@ get_visible_columns (NautilusListView *list_view) NautilusFile *file; GList *visible_columns; - file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (list_view)); + file = nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (list_view)); visible_columns = nautilus_file_get_metadata_list (file, @@ -2110,13 +2110,13 @@ get_default_column_order (NautilusListView *list_view) NautilusFile *file; NautilusDirectory *directory; - file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (list_view)); + file = nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (list_view)); if (nautilus_file_is_in_trash (file)) { return g_strdupv ((gchar **) default_trash_columns_order); } - directory = nautilus_view_get_model (NAUTILUS_VIEW (list_view)); + directory = nautilus_files_view_get_model (NAUTILUS_FILES_VIEW (list_view)); if (NAUTILUS_IS_SEARCH_DIRECTORY (directory)) { return g_strdupv ((gchar **) default_search_columns_order); } @@ -2131,7 +2131,7 @@ get_column_order (NautilusListView *list_view) NautilusFile *file; GList *column_order; - file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (list_view)); + file = nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (list_view)); column_order = nautilus_file_get_metadata_list (file, @@ -2179,7 +2179,7 @@ set_sort_order_from_metadata_and_preferences (NautilusListView *list_view) gboolean sort_reversed, default_sort_reversed; const gchar *default_sort_order; - file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (list_view)); + file = nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (list_view)); sort_attribute = nautilus_file_get_metadata (file, NAUTILUS_METADATA_KEY_LIST_VIEW_SORT_COLUMN, NULL); @@ -2220,7 +2220,7 @@ get_default_zoom_level (void) { } static void -nautilus_list_view_begin_loading (NautilusView *view) +nautilus_list_view_begin_loading (NautilusFilesView *view) { NautilusListView *list_view; @@ -2231,7 +2231,7 @@ nautilus_list_view_begin_loading (NautilusView *view) } static void -nautilus_list_view_clear (NautilusView *view) +nautilus_list_view_clear (NautilusFilesView *view) { NautilusListView *list_view; @@ -2243,7 +2243,7 @@ nautilus_list_view_clear (NautilusView *view) } static void -nautilus_list_view_file_changed (NautilusView *view, NautilusFile *file, NautilusDirectory *directory) +nautilus_list_view_file_changed (NautilusFilesView *view, NautilusFile *file, NautilusDirectory *directory) { NautilusListView *listview; @@ -2317,7 +2317,7 @@ tree_selection_has_common_parent (GtkTreeSelection *selection, } static char * -nautilus_list_view_get_backing_uri (NautilusView *view) +nautilus_list_view_get_backing_uri (NautilusFilesView *view) { NautilusListView *list_view; NautilusListModel *list_model; @@ -2382,7 +2382,7 @@ nautilus_list_view_get_backing_uri (NautilusView *view) /* Check that all the selected items belong to the same * directory and that directory is not the root directory (which - * is handled by NautilusView::get_backing_directory.) */ + * is handled by NautilusFilesView::get_backing_directory.) */ tree_selection_has_common_parent (selection, &is_common, &is_root); @@ -2403,7 +2403,7 @@ nautilus_list_view_get_backing_uri (NautilusView *view) return uri; } - return NAUTILUS_VIEW_CLASS (nautilus_list_view_parent_class)->get_backing_uri (view); + return NAUTILUS_FILES_VIEW_CLASS (nautilus_list_view_parent_class)->get_backing_uri (view); } static void @@ -2424,7 +2424,7 @@ nautilus_list_view_get_selection_foreach_func (GtkTreeModel *model, GtkTreePath } static GList * -nautilus_list_view_get_selection (NautilusView *view) +nautilus_list_view_get_selection (NautilusFilesView *view) { GList *list; @@ -2470,7 +2470,7 @@ nautilus_list_view_get_selection_for_file_transfer_foreach_func (GtkTreeModel *m static GList * -nautilus_list_view_get_selection_for_file_transfer (NautilusView *view) +nautilus_list_view_get_selection_for_file_transfer (NautilusFilesView *view) { struct SelectionForeachData selection_data; @@ -2484,13 +2484,13 @@ nautilus_list_view_get_selection_for_file_transfer (NautilusView *view) } static gboolean -nautilus_list_view_is_empty (NautilusView *view) +nautilus_list_view_is_empty (NautilusFilesView *view) { return nautilus_list_model_is_empty (NAUTILUS_LIST_VIEW (view)->details->model); } static void -nautilus_list_view_end_file_changes (NautilusView *view) +nautilus_list_view_end_file_changes (NautilusFilesView *view) { NautilusListView *list_view; @@ -2506,7 +2506,7 @@ nautilus_list_view_end_file_changes (NautilusView *view) } static void -nautilus_list_view_remove_file (NautilusView *view, NautilusFile *file, NautilusDirectory *directory) +nautilus_list_view_remove_file (NautilusFilesView *view, NautilusFile *file, NautilusDirectory *directory) { GtkTreePath *path; GtkTreePath *file_path; @@ -2565,7 +2565,7 @@ nautilus_list_view_remove_file (NautilusView *view, NautilusFile *file, Nautilus } static void -nautilus_list_view_set_selection (NautilusView *view, GList *selection) +nautilus_list_view_set_selection (NautilusFilesView *view, GList *selection) { NautilusListView *list_view; GtkTreeSelection *tree_selection; @@ -2591,11 +2591,11 @@ nautilus_list_view_set_selection (NautilusView *view, GList *selection) } g_signal_handlers_unblock_by_func (tree_selection, list_selection_changed_callback, view); - nautilus_view_notify_selection_changed (view); + nautilus_files_view_notify_selection_changed (view); } static void -nautilus_list_view_invert_selection (NautilusView *view) +nautilus_list_view_invert_selection (NautilusFilesView *view) { NautilusListView *list_view; GtkTreeSelection *tree_selection; @@ -2628,17 +2628,17 @@ nautilus_list_view_invert_selection (NautilusView *view) g_list_free (selection); g_signal_handlers_unblock_by_func (tree_selection, list_selection_changed_callback, view); - nautilus_view_notify_selection_changed (view); + nautilus_files_view_notify_selection_changed (view); } static void -nautilus_list_view_select_all (NautilusView *view) +nautilus_list_view_select_all (NautilusFilesView *view) { gtk_tree_selection_select_all (gtk_tree_view_get_selection (NAUTILUS_LIST_VIEW (view)->details->tree_view)); } static void -nautilus_list_view_select_first (NautilusView *view) +nautilus_list_view_select_first (NautilusFilesView *view) { GtkTreeSelection *selection; GtkTreeIter iter; @@ -2651,7 +2651,7 @@ nautilus_list_view_select_first (NautilusView *view) } static void -nautilus_list_view_zoom_to_level (NautilusView *view, +nautilus_list_view_zoom_to_level (NautilusFilesView *view, gint zoom_level) { NautilusListView *list_view; @@ -2665,10 +2665,10 @@ nautilus_list_view_zoom_to_level (NautilusView *view, } nautilus_list_view_set_zoom_level (list_view, zoom_level); - g_action_group_change_action_state (nautilus_view_get_action_group (view), + g_action_group_change_action_state (nautilus_files_view_get_action_group (view), "zoom-to-level", g_variant_new_int32 (zoom_level)); - nautilus_view_update_toolbar_menus (view); + nautilus_files_view_update_toolbar_menus (view); } static void @@ -2676,12 +2676,12 @@ action_zoom_to_level (GSimpleAction *action, GVariant *state, gpointer user_data) { - NautilusView *view; + NautilusFilesView *view; NautilusListZoomLevel zoom_level; - g_assert (NAUTILUS_IS_VIEW (user_data)); + g_assert (NAUTILUS_IS_FILES_VIEW (user_data)); - view = NAUTILUS_VIEW (user_data); + view = NAUTILUS_FILES_VIEW (user_data); zoom_level = g_variant_get_int32 (state); nautilus_list_view_zoom_to_level (view, zoom_level); @@ -2709,7 +2709,7 @@ column_chooser_changed_callback (NautilusColumnChooser *chooser, GList *list; int i; - file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (view)); + file = nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (view)); nautilus_column_chooser_get_settings (chooser, &visible_columns, @@ -2783,8 +2783,8 @@ column_chooser_use_default_callback (NautilusColumnChooser *chooser, char **default_columns; char **default_order; - file = nautilus_view_get_directory_as_file - (NAUTILUS_VIEW (view)); + file = nautilus_files_view_get_directory_as_file + (NAUTILUS_FILES_VIEW (view)); nautilus_file_set_metadata_list (file, NAUTILUS_METADATA_KEY_LIST_VIEW_COLUMN_ORDER, NULL); nautilus_file_set_metadata_list (file, NAUTILUS_METADATA_KEY_LIST_VIEW_VISIBLE_COLUMNS, NULL); @@ -2816,7 +2816,7 @@ create_column_editor (NautilusListView *view) char *name; const char *label_text; - file = nautilus_view_get_directory_as_file (NAUTILUS_VIEW (view)); + file = nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (view)); name = nautilus_file_get_display_name (file); str = g_strdup_printf (_("%s Visible Columns"), name); g_free (name); @@ -2924,7 +2924,7 @@ nautilus_list_view_set_zoom_level (NautilusListView *view, } static void -nautilus_list_view_bump_zoom_level (NautilusView *view, int zoom_increment) +nautilus_list_view_bump_zoom_level (NautilusFilesView *view, int zoom_increment) { NautilusListView *list_view; gint new_level; @@ -2941,7 +2941,7 @@ nautilus_list_view_bump_zoom_level (NautilusView *view, int zoom_increment) } static void -nautilus_list_view_restore_default_zoom_level (NautilusView *view) +nautilus_list_view_restore_default_zoom_level (NautilusFilesView *view) { g_return_if_fail (NAUTILUS_IS_LIST_VIEW (view)); @@ -2949,7 +2949,7 @@ nautilus_list_view_restore_default_zoom_level (NautilusView *view) } static gboolean -nautilus_list_view_can_zoom_in (NautilusView *view) +nautilus_list_view_can_zoom_in (NautilusFilesView *view) { g_return_val_if_fail (NAUTILUS_IS_LIST_VIEW (view), FALSE); @@ -2957,7 +2957,7 @@ nautilus_list_view_can_zoom_in (NautilusView *view) } static gboolean -nautilus_list_view_can_zoom_out (NautilusView *view) +nautilus_list_view_can_zoom_out (NautilusFilesView *view) { g_return_val_if_fail (NAUTILUS_IS_LIST_VIEW (view), FALSE); @@ -2965,7 +2965,7 @@ nautilus_list_view_can_zoom_out (NautilusView *view) } static void -nautilus_list_view_click_policy_changed (NautilusView *directory_view) +nautilus_list_view_click_policy_changed (NautilusFilesView *directory_view) { GdkWindow *win; GdkDisplay *display; @@ -3038,18 +3038,18 @@ default_column_order_changed_callback (gpointer callback_data) } static void -nautilus_list_view_sort_directories_first_changed (NautilusView *view) +nautilus_list_view_sort_directories_first_changed (NautilusFilesView *view) { NautilusListView *list_view; list_view = NAUTILUS_LIST_VIEW (view); nautilus_list_model_set_should_sort_directories_first (list_view->details->model, - nautilus_view_should_sort_directories_first (view)); + nautilus_files_view_should_sort_directories_first (view)); } static int -nautilus_list_view_compare_files (NautilusView *view, NautilusFile *file1, NautilusFile *file2) +nautilus_list_view_compare_files (NautilusFilesView *view, NautilusFile *file1, NautilusFile *file2) { NautilusListView *list_view; @@ -3058,7 +3058,7 @@ nautilus_list_view_compare_files (NautilusView *view, NautilusFile *file1, Nauti } static gboolean -nautilus_list_view_using_manual_layout (NautilusView *view) +nautilus_list_view_using_manual_layout (NautilusFilesView *view) { g_return_val_if_fail (NAUTILUS_IS_LIST_VIEW (view), FALSE); @@ -3140,7 +3140,7 @@ nautilus_list_view_finalize (GObject *object) } static char * -nautilus_list_view_get_first_visible_file (NautilusView *view) +nautilus_list_view_get_first_visible_file (NautilusFilesView *view) { NautilusFile *file; GtkTreePath *path; @@ -3196,7 +3196,7 @@ nautilus_list_view_scroll_to_file (NautilusListView *view, } static void -list_view_scroll_to_file (NautilusView *view, +list_view_scroll_to_file (NautilusFilesView *view, const char *uri) { NautilusFile *file; @@ -3232,7 +3232,7 @@ list_view_notify_clipboard_info (NautilusClipboardMonitor *monitor, } static void -nautilus_list_view_end_loading (NautilusView *view, +nautilus_list_view_end_loading (NautilusFilesView *view, gboolean all_files_seen) { NautilusClipboardMonitor *monitor; @@ -3245,13 +3245,13 @@ nautilus_list_view_end_loading (NautilusView *view, } static const char * -nautilus_list_view_get_id (NautilusView *view) +nautilus_list_view_get_id (NautilusFilesView *view) { return NAUTILUS_LIST_VIEW_ID; } static GdkRectangle* -nautilus_list_view_compute_rename_popover_relative_to (NautilusView *view) +nautilus_list_view_compute_rename_popover_relative_to (NautilusFilesView *view) { GtkTreeSelection *selection; GtkTreePath *path; @@ -3286,7 +3286,7 @@ nautilus_list_view_compute_rename_popover_relative_to (NautilusView *view) } static GIcon* -nautilus_list_view_get_icon (NautilusView *view) +nautilus_list_view_get_icon (NautilusFilesView *view) { g_return_val_if_fail (NAUTILUS_IS_LIST_VIEW (view), NULL); @@ -3296,42 +3296,42 @@ nautilus_list_view_get_icon (NautilusView *view) static void nautilus_list_view_class_init (NautilusListViewClass *class) { - NautilusViewClass *nautilus_view_class; + NautilusFilesViewClass *nautilus_files_view_class; - nautilus_view_class = NAUTILUS_VIEW_CLASS (class); + nautilus_files_view_class = NAUTILUS_FILES_VIEW_CLASS (class); G_OBJECT_CLASS (class)->dispose = nautilus_list_view_dispose; G_OBJECT_CLASS (class)->finalize = nautilus_list_view_finalize; - nautilus_view_class->add_file = nautilus_list_view_add_file; - nautilus_view_class->begin_loading = nautilus_list_view_begin_loading; - nautilus_view_class->end_loading = nautilus_list_view_end_loading; - nautilus_view_class->bump_zoom_level = nautilus_list_view_bump_zoom_level; - nautilus_view_class->can_zoom_in = nautilus_list_view_can_zoom_in; - nautilus_view_class->can_zoom_out = nautilus_list_view_can_zoom_out; - nautilus_view_class->click_policy_changed = nautilus_list_view_click_policy_changed; - nautilus_view_class->clear = nautilus_list_view_clear; - nautilus_view_class->file_changed = nautilus_list_view_file_changed; - nautilus_view_class->get_backing_uri = nautilus_list_view_get_backing_uri; - nautilus_view_class->get_selection = nautilus_list_view_get_selection; - 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->restore_default_zoom_level = nautilus_list_view_restore_default_zoom_level; - 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; - nautilus_view_class->set_selection = nautilus_list_view_set_selection; - nautilus_view_class->invert_selection = nautilus_list_view_invert_selection; - nautilus_view_class->compare_files = nautilus_list_view_compare_files; - nautilus_view_class->sort_directories_first_changed = nautilus_list_view_sort_directories_first_changed; - nautilus_view_class->end_file_changes = nautilus_list_view_end_file_changes; - nautilus_view_class->using_manual_layout = nautilus_list_view_using_manual_layout; - nautilus_view_class->get_view_id = nautilus_list_view_get_id; - nautilus_view_class->get_first_visible_file = nautilus_list_view_get_first_visible_file; - nautilus_view_class->scroll_to_file = list_view_scroll_to_file; - nautilus_view_class->compute_rename_popover_relative_to = nautilus_list_view_compute_rename_popover_relative_to; - nautilus_view_class->get_icon = nautilus_list_view_get_icon; + nautilus_files_view_class->add_file = nautilus_list_view_add_file; + nautilus_files_view_class->begin_loading = nautilus_list_view_begin_loading; + nautilus_files_view_class->end_loading = nautilus_list_view_end_loading; + nautilus_files_view_class->bump_zoom_level = nautilus_list_view_bump_zoom_level; + nautilus_files_view_class->can_zoom_in = nautilus_list_view_can_zoom_in; + nautilus_files_view_class->can_zoom_out = nautilus_list_view_can_zoom_out; + nautilus_files_view_class->click_policy_changed = nautilus_list_view_click_policy_changed; + nautilus_files_view_class->clear = nautilus_list_view_clear; + nautilus_files_view_class->file_changed = nautilus_list_view_file_changed; + nautilus_files_view_class->get_backing_uri = nautilus_list_view_get_backing_uri; + nautilus_files_view_class->get_selection = nautilus_list_view_get_selection; + nautilus_files_view_class->get_selection_for_file_transfer = nautilus_list_view_get_selection_for_file_transfer; + nautilus_files_view_class->is_empty = nautilus_list_view_is_empty; + nautilus_files_view_class->remove_file = nautilus_list_view_remove_file; + nautilus_files_view_class->restore_default_zoom_level = nautilus_list_view_restore_default_zoom_level; + nautilus_files_view_class->reveal_selection = nautilus_list_view_reveal_selection; + nautilus_files_view_class->select_all = nautilus_list_view_select_all; + nautilus_files_view_class->select_first = nautilus_list_view_select_first; + nautilus_files_view_class->set_selection = nautilus_list_view_set_selection; + nautilus_files_view_class->invert_selection = nautilus_list_view_invert_selection; + nautilus_files_view_class->compare_files = nautilus_list_view_compare_files; + nautilus_files_view_class->sort_directories_first_changed = nautilus_list_view_sort_directories_first_changed; + nautilus_files_view_class->end_file_changes = nautilus_list_view_end_file_changes; + nautilus_files_view_class->using_manual_layout = nautilus_list_view_using_manual_layout; + nautilus_files_view_class->get_view_id = nautilus_list_view_get_id; + nautilus_files_view_class->get_first_visible_file = nautilus_list_view_get_first_visible_file; + nautilus_files_view_class->scroll_to_file = list_view_scroll_to_file; + nautilus_files_view_class->compute_rename_popover_relative_to = nautilus_list_view_compute_rename_popover_relative_to; + nautilus_files_view_class->get_icon = nautilus_list_view_get_icon; } static void @@ -3364,9 +3364,9 @@ nautilus_list_view_init (NautilusListView *list_view) G_CALLBACK (default_column_order_changed_callback), list_view); - nautilus_list_view_click_policy_changed (NAUTILUS_VIEW (list_view)); + nautilus_list_view_click_policy_changed (NAUTILUS_FILES_VIEW (list_view)); - nautilus_list_view_sort_directories_first_changed (NAUTILUS_VIEW (list_view)); + nautilus_list_view_sort_directories_first_changed (NAUTILUS_FILES_VIEW (list_view)); nautilus_list_view_set_zoom_level (list_view, get_default_zoom_level ()); list_view->details->hover_path = NULL; @@ -3375,17 +3375,17 @@ nautilus_list_view_init (NautilusListView *list_view) "clipboard-info", G_CALLBACK (list_view_notify_clipboard_info), list_view); - view_action_group = nautilus_view_get_action_group (NAUTILUS_VIEW (list_view)); + view_action_group = nautilus_files_view_get_action_group (NAUTILUS_FILES_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); /* Keep the action synced with the actual value, so the toolbar can poll it */ - g_action_group_change_action_state (nautilus_view_get_action_group (NAUTILUS_VIEW (list_view)), + g_action_group_change_action_state (nautilus_files_view_get_action_group (NAUTILUS_FILES_VIEW (list_view)), "zoom-to-level", g_variant_new_int32 (get_default_zoom_level ())); } -NautilusView * +NautilusFilesView * nautilus_list_view_new (NautilusWindowSlot *slot) { return g_object_new (NAUTILUS_TYPE_LIST_VIEW, diff --git a/src/nautilus-list-view.h b/src/nautilus-list-view.h index caeee0830..03f027e82 100644 --- a/src/nautilus-list-view.h +++ b/src/nautilus-list-view.h @@ -26,7 +26,7 @@ #ifndef NAUTILUS_LIST_VIEW_H #define NAUTILUS_LIST_VIEW_H -#include "nautilus-view.h" +#include "nautilus-files-view.h" #define NAUTILUS_TYPE_LIST_VIEW nautilus_list_view_get_type() #define NAUTILUS_LIST_VIEW(obj) \ @@ -43,15 +43,15 @@ typedef struct NautilusListViewDetails NautilusListViewDetails; typedef struct { - NautilusView parent_instance; + NautilusFilesView parent_instance; NautilusListViewDetails *details; } NautilusListView; typedef struct { - NautilusViewClass parent_class; + NautilusFilesViewClass parent_class; } NautilusListViewClass; GType nautilus_list_view_get_type (void); -NautilusView * nautilus_list_view_new (NautilusWindowSlot *slot); +NautilusFilesView * nautilus_list_view_new (NautilusWindowSlot *slot); #endif /* NAUTILUS_LIST_VIEW_H */ diff --git a/src/nautilus-trash-bar.c b/src/nautilus-trash-bar.c index ac6630857..0508198e9 100644 --- a/src/nautilus-trash-bar.c +++ b/src/nautilus-trash-bar.c @@ -26,7 +26,7 @@ #include "nautilus-trash-bar.h" -#include "nautilus-view.h" +#include "nautilus-files-view.h" #include <libnautilus-private/nautilus-file-operations.h> #include <libnautilus-private/nautilus-file-utilities.h> #include <libnautilus-private/nautilus-file.h> @@ -47,19 +47,19 @@ enum { struct NautilusTrashBarPrivate { - NautilusView *view; + NautilusFilesView *view; gulong selection_handler_id; }; G_DEFINE_TYPE (NautilusTrashBar, nautilus_trash_bar, GTK_TYPE_INFO_BAR); static void -selection_changed_cb (NautilusView *view, +selection_changed_cb (NautilusFilesView *view, NautilusTrashBar *bar) { int count; - count = nautilus_view_get_selection_count (view); + count = nautilus_files_view_get_selection_count (view); gtk_info_bar_set_response_sensitive (GTK_INFO_BAR (bar), TRASH_BAR_RESPONSE_RESTORE, @@ -140,8 +140,8 @@ nautilus_trash_bar_class_init (NautilusTrashBarClass *klass) PROP_VIEW, g_param_spec_object ("view", "view", - "the NautilusView", - NAUTILUS_TYPE_VIEW, + "the NautilusFilesView", + NAUTILUS_TYPE_FILES_VIEW, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); @@ -166,7 +166,7 @@ trash_bar_response_cb (GtkInfoBar *infobar, nautilus_file_operations_empty_trash (window); break; case TRASH_BAR_RESPONSE_RESTORE: - files = nautilus_view_get_selection (bar->priv->view); + files = nautilus_files_view_get_selection (bar->priv->view); nautilus_restore_files_from_trash (files, GTK_WINDOW (window)); nautilus_file_list_free (files); break; @@ -224,7 +224,7 @@ nautilus_trash_bar_init (NautilusTrashBar *bar) } GtkWidget * -nautilus_trash_bar_new (NautilusView *view) +nautilus_trash_bar_new (NautilusFilesView *view) { return g_object_new (NAUTILUS_TYPE_TRASH_BAR, "view", view, diff --git a/src/nautilus-trash-bar.h b/src/nautilus-trash-bar.h index 9190415fd..234cc84d0 100644 --- a/src/nautilus-trash-bar.h +++ b/src/nautilus-trash-bar.h @@ -22,7 +22,7 @@ #ifndef __NAUTILUS_TRASH_BAR_H #define __NAUTILUS_TRASH_BAR_H -#include "nautilus-view.h" +#include "nautilus-files-view.h" #include <gtk/gtk.h> @@ -51,7 +51,7 @@ typedef struct GType nautilus_trash_bar_get_type (void) G_GNUC_CONST; -GtkWidget *nautilus_trash_bar_new (NautilusView *view); +GtkWidget *nautilus_trash_bar_new (NautilusFilesView *view); G_END_DECLS diff --git a/src/nautilus-view-dnd.c b/src/nautilus-view-dnd.c deleted file mode 100644 index d9fe0fe69..000000000 --- a/src/nautilus-view-dnd.c +++ /dev/null @@ -1,546 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* - * nautilus-view-dnd.c: DnD helpers for NautilusView - * - * Copyright (C) 1999, 2000 Free Software Foundaton - * Copyright (C) 2000, 2001 Eazel, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, see <http://www.gnu.org/licenses/>. - * - * Authors: Ettore Perazzoli - * Darin Adler <darin@bentspoon.com> - * John Sullivan <sullivan@eazel.com> - * Pavel Cisler <pavel@eazel.com> - */ - -#include <config.h> - -#include "nautilus-view-dnd.h" - -#include "nautilus-view.h" - -#include <eel/eel-stock-dialogs.h> -#include <eel/eel-string.h> - -#include <glib/gi18n.h> - -#include <libnautilus-private/nautilus-clipboard.h> -#include <libnautilus-private/nautilus-dnd.h> - -#define GET_ANCESTOR(obj) \ - GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (obj), GTK_TYPE_WINDOW)) - -static inline void -view_widget_to_file_operation_position (NautilusView *view, - GdkPoint *position) -{ - NautilusViewClass *class = NAUTILUS_VIEW_GET_CLASS (view); - - if (class->widget_to_file_operation_position != NULL) { - class->widget_to_file_operation_position (view, position); - } -} - -static void -view_widget_to_file_operation_position_xy (NautilusView *view, - int *x, int *y) -{ - GdkPoint position; - - position.x = *x; - position.y = *y; - view_widget_to_file_operation_position (view, &position); - *x = position.x; - *y = position.y; -} - -typedef struct { - NautilusView *view; - char *link_name; - char *target_uri; - char *url; - GdkPoint point; -} NetscapeUrlDropLink; - -static void -revert_slashes (char *string) -{ - while (*string != 0) { - if (*string == '/') { - *string = '\\'; - } - string++; - } -} - -static void -handle_netscape_url_drop_link_cb (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - NetscapeUrlDropLink *data = user_data; - char *link_name = data->link_name; - char *link_display_name; - gint screen_num; - GFileInfo *info; - char *icon_name = NULL; - GdkScreen *screen; - - info = g_file_query_info_finish (G_FILE (source_object), - res, NULL); - - if (info != NULL) { - GIcon *icon; - const char * const *names; - - icon = g_file_info_get_icon (info); - - if (G_IS_THEMED_ICON (icon)) { - names = g_themed_icon_get_names (G_THEMED_ICON (icon)); - icon_name = g_strdup (names[0]); - } - - g_object_unref (info); - } - - if (icon_name == NULL) { - icon_name = g_strdup ("text-html"); - } - - link_display_name = g_strdup_printf (_("Link to %s"), link_name); - - /* The filename can't contain slashes, strip em. - (the basename of http://foo/ is http://foo/) */ - revert_slashes (link_name); - - screen = gtk_widget_get_screen (GTK_WIDGET (data->view)); - screen_num = gdk_screen_get_number (screen); - - nautilus_link_local_create (data->target_uri, - link_name, - link_display_name, - icon_name, - data->url, - &data->point, - screen_num, - TRUE); - - g_free (link_display_name); - g_free (icon_name); - - g_free (data->url); - g_free (data->link_name); - g_free (data->target_uri); - - g_object_unref (data->view); - g_slice_free (NetscapeUrlDropLink, data); -} - -void -nautilus_view_handle_netscape_url_drop (NautilusView *view, - const char *encoded_url, - const char *target_uri, - GdkDragAction action, - int x, - int y) -{ - char *url, *title; - char *link_name; - GArray *points; - char **bits; - GList *uri_list = NULL; - GFile *f; - - f = g_file_new_for_uri (target_uri); - - if (!g_file_is_native (f)) { - eel_show_warning_dialog (_("Drag and drop is not supported."), - _("Drag and drop is only supported on local file systems."), - GET_ANCESTOR (view)); - g_object_unref (f); - return; - } - - g_object_unref (f); - - /* _NETSCAPE_URL_ works like this: $URL\n$TITLE */ - bits = g_strsplit (encoded_url, "\n", 0); - switch (g_strv_length (bits)) { - case 0: - g_strfreev (bits); - return; - case 1: - url = bits[0]; - title = NULL; - break; - default: - url = bits[0]; - title = bits[1]; - } - - f = g_file_new_for_uri (url); - - view_widget_to_file_operation_position_xy (view, &x, &y); - - /* We don't support GDK_ACTION_ASK or GDK_ACTION_PRIVATE - * and we don't support combinations either. */ - if ((action != GDK_ACTION_DEFAULT) && - (action != GDK_ACTION_COPY) && - (action != GDK_ACTION_MOVE) && - (action != GDK_ACTION_LINK)) { - eel_show_warning_dialog (_("Drag and drop is not supported."), - _("An invalid drag type was used."), - GET_ANCESTOR (view)); - return; - } - - if (action == GDK_ACTION_LINK) { - if (g_strcmp0 (title, NULL) == 0) { - link_name = g_file_get_basename (f); - } else { - link_name = g_strdup (title); - } - - if (g_strcmp0 (link_name, NULL) != 0) { - NetscapeUrlDropLink *data; - - data = g_slice_new0 (NetscapeUrlDropLink); - data->link_name = link_name; - data->point.x = x; - data->point.y = y; - data->view = g_object_ref (view); - data->target_uri = g_strdup (target_uri); - data->url = g_strdup (url); - - g_file_query_info_async (f, - G_FILE_ATTRIBUTE_STANDARD_ICON, - 0, 0, NULL, - handle_netscape_url_drop_link_cb, - data); - } - } else { - GdkPoint tmp_point = { 0, 0 }; - - /* pass in a 1-item array of icon positions, relative to x, y */ - points = g_array_new (FALSE, TRUE, sizeof (GdkPoint)); - g_array_append_val (points, tmp_point); - - uri_list = g_list_append (uri_list, url); - - nautilus_view_move_copy_items (view, uri_list, points, - target_uri, - action, x, y); - - g_list_free (uri_list); - g_array_free (points, TRUE); - } - - g_object_unref (f); - g_strfreev (bits); -} - -void -nautilus_view_handle_uri_list_drop (NautilusView *view, - const char *item_uris, - const char *target_uri, - GdkDragAction action, - int x, - int y) -{ - gchar **uri_list; - GList *real_uri_list = NULL; - char *container_uri; - int n_uris, i; - GArray *points; - - if (item_uris == NULL) { - return; - } - - container_uri = NULL; - if (target_uri == NULL) { - container_uri = nautilus_view_get_backing_uri (view); - g_assert (container_uri != NULL); - } - - if (action == GDK_ACTION_ASK) { - action = nautilus_drag_drop_action_ask - (GTK_WIDGET (view), - GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK); - if (action == 0) { - g_free (container_uri); - return; - } - } - - /* We don't support GDK_ACTION_ASK or GDK_ACTION_PRIVATE - * and we don't support combinations either. */ - if ((action != GDK_ACTION_DEFAULT) && - (action != GDK_ACTION_COPY) && - (action != GDK_ACTION_MOVE) && - (action != GDK_ACTION_LINK)) { - eel_show_warning_dialog (_("Drag and drop is not supported."), - _("An invalid drag type was used."), - GET_ANCESTOR (view)); - g_free (container_uri); - return; - } - - n_uris = 0; - uri_list = g_uri_list_extract_uris (item_uris); - for (i = 0; uri_list[i] != NULL; i++) { - real_uri_list = g_list_append (real_uri_list, uri_list[i]); - n_uris++; - } - g_free (uri_list); - - /* do nothing if no real uris are left */ - if (n_uris == 0) { - g_free (container_uri); - return; - } - - if (n_uris == 1) { - GdkPoint tmp_point = { 0, 0 }; - - /* pass in a 1-item array of icon positions, relative to x, y */ - points = g_array_new (FALSE, TRUE, sizeof (GdkPoint)); - g_array_append_val (points, tmp_point); - } else { - points = NULL; - } - - view_widget_to_file_operation_position_xy (view, &x, &y); - - nautilus_view_move_copy_items (view, real_uri_list, points, - target_uri != NULL ? target_uri : container_uri, - action, x, y); - - g_list_free_full (real_uri_list, g_free); - - if (points != NULL) - g_array_free (points, TRUE); - - g_free (container_uri); -} - -#define MAX_LEN_FILENAME 128 -#define MIN_LEN_FILENAME 10 - -static char * -get_drop_filename (const char *text) -{ - char *filename; - char trimmed[MAX_LEN_FILENAME]; - int i; - int last_word = -1; - int last_sentence = -1; - int last_nonspace = -1; - int num_attrs; - PangoLogAttr *attrs; - gchar *current_char; - - num_attrs = MIN (g_utf8_strlen (text, -1), MAX_LEN_FILENAME) + 1; - attrs = g_new (PangoLogAttr, num_attrs); - g_utf8_strncpy (trimmed, text, num_attrs - 1); - pango_get_log_attrs (trimmed, -1, -1, pango_language_get_default (), attrs, num_attrs); - - /* since the end of the text will always match a word boundary don't include it */ - for (i = 0; (i < num_attrs - 1); i++) { - if (!attrs[i].is_white) - last_nonspace = i; - if (attrs[i].is_sentence_end) - last_sentence = last_nonspace; - if (attrs[i].is_word_boundary) - last_word = last_nonspace; - } - g_free (attrs); - - if (last_sentence > 0) - i = last_sentence; - else - i = last_word; - - if (i > MIN_LEN_FILENAME) { - char basename[MAX_LEN_FILENAME]; - g_utf8_strncpy (basename, trimmed, i); - filename = g_strdup_printf ("%s.txt", basename); - } else { - /* Translator: This is the filename used for when you dnd text to a directory */ - filename = g_strdup (_("Dropped Text.txt")); - } - - /* Remove any invalid characters */ - for (current_char = filename; - *current_char; - current_char = g_utf8_next_char (current_char)) { - if ( G_IS_DIR_SEPARATOR ( g_utf8_get_char (current_char))) { - *current_char = '-'; - } - } - - return filename; -} - -void -nautilus_view_handle_text_drop (NautilusView *view, - const char *text, - const char *target_uri, - GdkDragAction action, - int x, - int y) -{ - int length; - char *container_uri; - GdkPoint pos; - char *filename; - - if (text == NULL) { - return; - } - - g_return_if_fail (action == GDK_ACTION_COPY); - - container_uri = NULL; - if (target_uri == NULL) { - container_uri = nautilus_view_get_backing_uri (view); - g_assert (container_uri != NULL); - } - - length = strlen (text); - - pos.x = x; - pos.y = y; - view_widget_to_file_operation_position (view, &pos); - - /* try to get text to use as a filename */ - filename = get_drop_filename (text); - - nautilus_view_new_file_with_initial_contents (view, - target_uri != NULL ? target_uri : container_uri, - filename, - text, - length, - &pos); - g_free (filename); - g_free (container_uri); -} - -void -nautilus_view_handle_raw_drop (NautilusView *view, - const char *raw_data, - int length, - const char *target_uri, - const char *direct_save_uri, - GdkDragAction action, - int x, - int y) -{ - char *container_uri, *filename; - GFile *direct_save_full; - GdkPoint pos; - - if (raw_data == NULL) { - return; - } - - g_return_if_fail (action == GDK_ACTION_COPY); - - container_uri = NULL; - if (target_uri == NULL) { - container_uri = nautilus_view_get_backing_uri (view); - g_assert (container_uri != NULL); - } - - pos.x = x; - pos.y = y; - view_widget_to_file_operation_position (view, &pos); - - filename = NULL; - if (direct_save_uri != NULL) { - direct_save_full = g_file_new_for_uri (direct_save_uri); - filename = g_file_get_basename (direct_save_full); - } - if (filename == NULL) { - /* Translator: This is the filename used for when you dnd raw - * data to a directory, if the source didn't supply a name. - */ - filename = g_strdup (_("dropped data")); - } - - nautilus_view_new_file_with_initial_contents ( - view, target_uri != NULL ? target_uri : container_uri, - filename, raw_data, length, &pos); - - g_free (container_uri); - g_free (filename); -} - -void -nautilus_view_drop_proxy_received_uris (NautilusView *view, - const GList *source_uri_list, - const char *target_uri, - GdkDragAction action) -{ - char *container_uri; - - container_uri = NULL; - if (target_uri == NULL) { - container_uri = nautilus_view_get_backing_uri (view); - g_assert (container_uri != NULL); - } - - if (action == GDK_ACTION_ASK) { - action = nautilus_drag_drop_action_ask - (GTK_WIDGET (view), - GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK); - if (action == 0) { - return; - } - } - - nautilus_clipboard_clear_if_colliding_uris (GTK_WIDGET (view), - source_uri_list, - nautilus_view_get_copied_files_atom (view)); - - nautilus_view_move_copy_items (view, source_uri_list, NULL, - target_uri != NULL ? target_uri : container_uri, - action, 0, 0); - - g_free (container_uri); -} - -void -nautilus_view_handle_hover (NautilusView *view, - const char *target_uri) -{ - NautilusWindowSlot *slot; - GFile *location; - GFile *current_location; - NautilusFile *target_file; - gboolean target_is_dir; - - slot = nautilus_view_get_nautilus_window_slot (view); - - location = g_file_new_for_uri (target_uri); - target_file = nautilus_file_get_existing (location); - target_is_dir = nautilus_file_get_file_type (target_file) == G_FILE_TYPE_DIRECTORY; - current_location = nautilus_window_slot_get_location (slot); - if (target_is_dir && ! (current_location != NULL && g_file_equal(location, current_location))) { - nautilus_window_slot_open_location (slot, location, 0); - } - g_object_unref (location); - nautilus_file_unref (target_file); -} diff --git a/src/nautilus-view-dnd.h b/src/nautilus-view-dnd.h deleted file mode 100644 index bd09af404..000000000 --- a/src/nautilus-view-dnd.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* - * nautilus-view-dnd.h: DnD helpers for NautilusView - * - * Copyright (C) 1999, 2000 Free Software Foundaton - * Copyright (C) 2000, 2001 Eazel, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, see <http://www.gnu.org/licenses/>. - * - * Authors: Ettore Perazzoli - * Darin Adler <darin@bentspoon.com> - * John Sullivan <sullivan@eazel.com> - * Pavel Cisler <pavel@eazel.com> - */ - -#ifndef __NAUTILUS_VIEW_DND_H__ -#define __NAUTILUS_VIEW_DND_H__ - -#include "nautilus-view.h" - -void nautilus_view_handle_netscape_url_drop (NautilusView *view, - const char *encoded_url, - const char *target_uri, - GdkDragAction action, - int x, - int y); -void nautilus_view_handle_uri_list_drop (NautilusView *view, - const char *item_uris, - const char *target_uri, - GdkDragAction action, - int x, - int y); -void nautilus_view_handle_text_drop (NautilusView *view, - const char *text, - const char *target_uri, - GdkDragAction action, - int x, - int y); -void nautilus_view_handle_raw_drop (NautilusView *view, - const char *raw_data, - int length, - const char *target_uri, - const char *direct_save_uri, - GdkDragAction action, - int x, - int y); -void nautilus_view_handle_hover (NautilusView *view, - const char *target_uri); - -void nautilus_view_drop_proxy_received_uris (NautilusView *view, - const GList *uris, - const char *target_location, - GdkDragAction action); - - -#endif /* __NAUTILUS_VIEW_DND_H__ */ diff --git a/src/nautilus-view.c b/src/nautilus-view.c deleted file mode 100644 index 752334f4d..000000000 --- a/src/nautilus-view.c +++ /dev/null @@ -1,8113 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ - -/* nautilus-view.c - * - * Copyright (C) 1999, 2000 Free Software Foundation - * Copyright (C) 2000, 2001 Eazel, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, see <http://www.gnu.org/licenses/>. - * - * Authors: Ettore Perazzoli, - * John Sullivan <sullivan@eazel.com>, - * Darin Adler <darin@bentspoon.com>, - * Pavel Cisler <pavel@eazel.com>, - * David Emory Watson <dwatson@cs.ucr.edu> - */ - -#include <config.h> - -#include "nautilus-view.h" - -#include "nautilus-application.h" -#include "nautilus-desktop-canvas-view.h" -#include "nautilus-error-reporting.h" -#include "nautilus-floating-bar.h" -#include "nautilus-list-view.h" -#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" -#endif - -#ifdef HAVE_X11_XF86KEYSYM_H -#include <X11/XF86keysym.h> -#endif - -#include <gdk/gdkx.h> -#include <gdk/gdkkeysyms.h> -#include <gtk/gtk.h> -#include <glib/gi18n.h> -#include <glib/gstdio.h> -#include <gio/gio.h> -#include <math.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -#include <eel/eel-glib-extensions.h> -#include <eel/eel-gnome-extensions.h> -#include <eel/eel-gtk-extensions.h> -#include <eel/eel-stock-dialogs.h> -#include <eel/eel-string.h> -#include <eel/eel-vfs-extensions.h> - -#include <libnautilus-extension/nautilus-menu-provider.h> -#include <libnautilus-private/nautilus-clipboard.h> -#include <libnautilus-private/nautilus-clipboard-monitor.h> -#include <libnautilus-private/nautilus-desktop-icon-file.h> -#include <libnautilus-private/nautilus-desktop-directory.h> -#include <libnautilus-private/nautilus-search-directory.h> -#include <libnautilus-private/nautilus-directory.h> -#include <libnautilus-private/nautilus-dnd.h> -#include <libnautilus-private/nautilus-file-attributes.h> -#include <libnautilus-private/nautilus-file-changes-queue.h> -#include <libnautilus-private/nautilus-file-dnd.h> -#include <libnautilus-private/nautilus-file-operations.h> -#include <libnautilus-private/nautilus-file-utilities.h> -#include <libnautilus-private/nautilus-file-private.h> -#include <libnautilus-private/nautilus-global-preferences.h> -#include <libnautilus-private/nautilus-link.h> -#include <libnautilus-private/nautilus-metadata.h> -#include <libnautilus-private/nautilus-recent.h> -#include <libnautilus-private/nautilus-module.h> -#include <libnautilus-private/nautilus-profile.h> -#include <libnautilus-private/nautilus-program-choosing.h> -#include <libnautilus-private/nautilus-trash-monitor.h> -#include <libnautilus-private/nautilus-ui-utilities.h> -#include <libnautilus-private/nautilus-signaller.h> -#include <libnautilus-private/nautilus-icon-names.h> - -#define GNOME_DESKTOP_USE_UNSTABLE_API -#include <gdesktop-enums.h> - -#define DEBUG_FLAG NAUTILUS_DEBUG_DIRECTORY_VIEW -#include <libnautilus-private/nautilus-debug.h> - -/* Minimum starting update inverval */ -#define UPDATE_INTERVAL_MIN 100 -/* Maximum update interval */ -#define UPDATE_INTERVAL_MAX 2000 -/* Amount of miliseconds the update interval is increased */ -#define UPDATE_INTERVAL_INC 250 -/* Interval at which the update interval is increased */ -#define UPDATE_INTERVAL_TIMEOUT_INTERVAL 250 -/* Milliseconds that have to pass without a change to reset the update interval */ -#define UPDATE_INTERVAL_RESET 1000 - -#define SILENT_WINDOW_OPEN_LIMIT 5 - -#define DUPLICATE_HORIZONTAL_ICON_OFFSET 70 -#define DUPLICATE_VERTICAL_ICON_OFFSET 30 - -#define MAX_QUEUED_UPDATES 500 - -#define MAX_MENU_LEVELS 5 -#define TEMPLATE_LIMIT 30 - -/* Delay to show the duplicated label when creating a folder */ -#define FILE_NAME_DUPLICATED_LABEL_TIMEOUT 500 - -/* Delay to show the Loading... floating bar */ -#define FLOATING_BAR_LOADING_DELAY 500 /* ms */ - -enum { - ADD_FILE, - BEGIN_FILE_CHANGES, - BEGIN_LOADING, - CLEAR, - END_FILE_CHANGES, - END_LOADING, - FILE_CHANGED, - MOVE_COPY_ITEMS, - REMOVE_FILE, - SELECTION_CHANGED, - TRASH, - DELETE, - LAST_SIGNAL -}; - -enum { - PROP_WINDOW_SLOT = 1, - PROP_SUPPORTS_ZOOMING, - PROP_ICON, - PROP_VIEW_WIDGET, - NUM_PROPERTIES -}; - -static guint signals[LAST_SIGNAL]; -static GParamSpec *properties[NUM_PROPERTIES] = { NULL, }; - -static GdkAtom copied_files_atom; - -static char *scripts_directory_uri = NULL; -static int scripts_directory_uri_length; - -struct NautilusViewDetails -{ - NautilusWindowSlot *slot; - NautilusDirectory *model; - NautilusFile *directory_as_file; - guint dir_merge_id; - - gint duplicated_label_timeout_id; - GtkWidget *rename_file_popover; - - gboolean supports_zooming; - - GList *scripts_directory_list; - GList *templates_directory_list; - - guint display_selection_idle_id; - guint update_context_menus_timeout_id; - guint update_status_idle_id; - guint reveal_selection_idle_id; - - guint display_pending_source_id; - guint changes_timeout_id; - - guint update_interval; - guint64 last_queued; - - guint files_added_handler_id; - guint files_changed_handler_id; - guint load_error_handler_id; - guint done_loading_handler_id; - guint file_changed_handler_id; - - GList *new_added_files; - GList *new_changed_files; - - GHashTable *non_ready_files; - - GList *old_added_files; - GList *old_changed_files; - - GList *pending_selection; - - /* whether we are in the active slot */ - gboolean active; - - /* loading indicates whether this view has begun loading a directory. - * This flag should need not be set inside subclasses. NautilusView automatically - * sets 'loading' to TRUE before it begins loading a directory's contents and to FALSE - * after it finishes loading the directory and its view. - */ - gboolean loading; - gboolean templates_present; - gboolean scripts_present; - - gboolean sort_directories_first; - - gboolean show_foreign_files; - gboolean show_hidden_files; - gboolean ignore_hidden_file_preferences; - - gboolean batching_selection_level; - gboolean selection_changed_while_batched; - - gboolean selection_was_removed; - - gboolean metadata_for_directory_as_file_pending; - gboolean metadata_for_files_in_directory_pending; - - GList *subdirectory_list; - - GdkPoint context_menu_position; - - GMenu *selection_menu; - GMenu *background_menu; - - GActionGroup *view_action_group; - - GtkWidget *scrolled_window; - - /* Empty states */ - GtkWidget *folder_is_empty_widget; - GtkWidget *no_search_results_widget; - - /* Floating bar */ - guint floating_bar_set_status_timeout_id; - guint floating_bar_loading_timeout_id; - GtkWidget *floating_bar; - - /* View menu */ - GtkWidget *view_menu_widget; - GtkWidget *view_icon; - GtkWidget *sort_menu; - GtkWidget *sort_trash_time; - GtkWidget *sort_search_relevance; - GtkWidget *visible_columns; - GtkWidget *stop; - GtkWidget *reload; - GtkAdjustment *zoom_adjustment; - GtkWidget *zoom_level_scale; - - gulong stop_signal_handler; - gulong reload_signal_handler; -}; - -typedef struct { - NautilusFile *file; - NautilusDirectory *directory; -} FileAndDirectory; - -/* forward declarations */ - -static gboolean display_selection_info_idle_callback (gpointer data); -static void trash_or_delete_files (GtkWindow *parent_window, - const GList *files, - NautilusView *view); -static void load_directory (NautilusView *view, - NautilusDirectory *directory); -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_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); -static void schedule_idle_display_of_pending_files (NautilusView *view); -static void unschedule_display_of_pending_files (NautilusView *view); -static void disconnect_model_handlers (NautilusView *view); -static void metadata_for_directory_as_file_ready_callback (NautilusFile *file, - gpointer callback_data); -static void metadata_for_files_in_directory_ready_callback (NautilusDirectory *directory, - GList *files, - gpointer callback_data); -static void nautilus_view_trash_state_changed_callback (NautilusTrashMonitor *trash, - gboolean state, - gpointer callback_data); -static void nautilus_view_select_file (NautilusView *view, - NautilusFile *file); - -static void update_templates_directory (NautilusView *view); - -static void check_empty_states (NautilusView *view); - -G_DEFINE_TYPE (NautilusView, nautilus_view, GTK_TYPE_OVERLAY); - -static const struct { - unsigned int keyval; - const char *action; -} extra_view_keybindings [] = { -#ifdef HAVE_X11_XF86KEYSYM_H - /* View actions */ - { XF86XK_ZoomIn, "zoom-in" }, - { XF86XK_ZoomOut, "zoom-out" }, - -#endif -}; - -static void -check_empty_states (NautilusView *view) -{ - GList *files; - GList *filtered; - gboolean show_hidden_files; - - gtk_widget_hide (view->details->no_search_results_widget); - gtk_widget_hide (view->details->folder_is_empty_widget); - if (!view->details->loading && view->details->model) { - files = nautilus_directory_get_file_list (view->details->model); - show_hidden_files = g_settings_get_boolean (gtk_filechooser_preferences, - NAUTILUS_PREFERENCES_SHOW_HIDDEN_FILES); - filtered = nautilus_file_list_filter_hidden (files, show_hidden_files); - if (g_list_length (filtered) == 0) { - if (nautilus_view_is_search (view)) { - gtk_widget_show (view->details->no_search_results_widget); - } else { - gtk_widget_show (view->details->folder_is_empty_widget); - } - } - nautilus_file_list_unref (filtered); - nautilus_file_list_unref (files); - } -} - -/* - * Floating Bar code - */ -static void -remove_loading_floating_bar (NautilusView *view) -{ - if (view->details->floating_bar_loading_timeout_id != 0) { - g_source_remove (view->details->floating_bar_loading_timeout_id); - view->details->floating_bar_loading_timeout_id = 0; - } - - gtk_widget_hide (view->details->floating_bar); - nautilus_floating_bar_cleanup_actions (NAUTILUS_FLOATING_BAR (view->details->floating_bar)); -} - -static void -real_setup_loading_floating_bar (NautilusView *view) -{ - gboolean disable_chrome; - - g_object_get (nautilus_view_get_window (view), - "disable-chrome", &disable_chrome, - NULL); - - if (disable_chrome) { - gtk_widget_hide (view->details->floating_bar); - return; - } - - nautilus_floating_bar_cleanup_actions (NAUTILUS_FLOATING_BAR (view->details->floating_bar)); - nautilus_floating_bar_set_primary_label (NAUTILUS_FLOATING_BAR (view->details->floating_bar), - nautilus_view_is_search (view) ? _("Searching…") : _("Loading…")); - nautilus_floating_bar_set_details_label (NAUTILUS_FLOATING_BAR (view->details->floating_bar), NULL); - nautilus_floating_bar_set_show_spinner (NAUTILUS_FLOATING_BAR (view->details->floating_bar), view->details->loading); - nautilus_floating_bar_add_action (NAUTILUS_FLOATING_BAR (view->details->floating_bar), - "process-stop-symbolic", - NAUTILUS_FLOATING_BAR_ACTION_ID_STOP); - - gtk_widget_set_halign (view->details->floating_bar, GTK_ALIGN_END); - gtk_widget_show (view->details->floating_bar); -} - -static gboolean -setup_loading_floating_bar_timeout_cb (gpointer user_data) -{ - NautilusView *view = user_data; - - view->details->floating_bar_loading_timeout_id = 0; - real_setup_loading_floating_bar (view); - - return FALSE; -} - -static void -setup_loading_floating_bar (NautilusView *view) -{ - /* setup loading overlay */ - if (view->details->floating_bar_set_status_timeout_id != 0) { - g_source_remove (view->details->floating_bar_set_status_timeout_id); - view->details->floating_bar_set_status_timeout_id = 0; - } - - if (view->details->floating_bar_loading_timeout_id != 0) { - g_source_remove (view->details->floating_bar_loading_timeout_id); - view->details->floating_bar_loading_timeout_id = 0; - } - - view->details->floating_bar_loading_timeout_id = - g_timeout_add (FLOATING_BAR_LOADING_DELAY, setup_loading_floating_bar_timeout_cb, view); -} - -static void -floating_bar_action_cb (NautilusFloatingBar *floating_bar, - gint action, - NautilusView *view) -{ - if (action == NAUTILUS_FLOATING_BAR_ACTION_ID_STOP) { - remove_loading_floating_bar (view); - nautilus_window_slot_stop_loading (view->details->slot); - } -} - -static void -real_floating_bar_set_short_status (NautilusView *view, - const gchar *primary_status, - const gchar *detail_status) -{ - gboolean disable_chrome; - - nautilus_floating_bar_cleanup_actions (NAUTILUS_FLOATING_BAR (view->details->floating_bar)); - nautilus_floating_bar_set_show_spinner (NAUTILUS_FLOATING_BAR (view->details->floating_bar), view->details->loading); - - g_object_get (nautilus_view_get_window (view), - "disable-chrome", &disable_chrome, - NULL); - - if ((primary_status == NULL && detail_status == NULL) || disable_chrome) { - gtk_widget_hide (view->details->floating_bar); - return; - } - - nautilus_floating_bar_set_labels (NAUTILUS_FLOATING_BAR (view->details->floating_bar), - primary_status, - detail_status); - - gtk_widget_show (view->details->floating_bar); -} - -typedef struct { - gchar *primary_status; - gchar *detail_status; - NautilusView *view; -} FloatingBarSetStatusData; - -static void -floating_bar_set_status_data_free (gpointer data) -{ - FloatingBarSetStatusData *status_data = data; - - g_free (status_data->primary_status); - g_free (status_data->detail_status); - - g_slice_free (FloatingBarSetStatusData, data); -} - -static gboolean -floating_bar_set_status_timeout_cb (gpointer data) -{ - FloatingBarSetStatusData *status_data = data; - - status_data->view->details->floating_bar_set_status_timeout_id = 0; - real_floating_bar_set_short_status (status_data->view, - status_data->primary_status, - status_data->detail_status); - - return FALSE; -} - -static void -set_floating_bar_status (NautilusView *view, - const gchar *primary_status, - const gchar *detail_status) -{ - GtkSettings *settings; - gint double_click_time; - FloatingBarSetStatusData *status_data; - - if (view->details->floating_bar_set_status_timeout_id != 0) { - g_source_remove (view->details->floating_bar_set_status_timeout_id); - view->details->floating_bar_set_status_timeout_id = 0; - } - - settings = gtk_settings_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (view))); - g_object_get (settings, - "gtk-double-click-time", &double_click_time, - NULL); - - status_data = g_slice_new0 (FloatingBarSetStatusData); - status_data->primary_status = g_strdup (primary_status); - status_data->detail_status = g_strdup (detail_status); - status_data->view = view; - - /* waiting for half of the double-click-time before setting - * the status seems to be a good approximation of not setting it - * too often and not delaying the statusbar too much. - */ - view->details->floating_bar_set_status_timeout_id = - g_timeout_add_full (G_PRIORITY_DEFAULT, - (guint) (double_click_time / 2), - floating_bar_set_status_timeout_cb, - status_data, - floating_bar_set_status_data_free); -} - -static char * -real_get_backing_uri (NautilusView *view) -{ - NautilusDirectory *directory; - char *uri; - - g_return_val_if_fail (NAUTILUS_IS_VIEW (view), NULL); - - if (view->details->model == NULL) { - return NULL; - } - - directory = view->details->model; - - if (NAUTILUS_IS_DESKTOP_DIRECTORY (directory)) { - directory = nautilus_desktop_directory_get_real_directory (NAUTILUS_DESKTOP_DIRECTORY (directory)); - } else { - nautilus_directory_ref (directory); - } - - uri = nautilus_directory_get_uri (directory); - - nautilus_directory_unref (directory); - - return uri; -} - -/** - * - * nautilus_view_get_backing_uri: - * - * Returns the URI for the target location of new directory, new file, new - * link and paste operations. - */ - -char * -nautilus_view_get_backing_uri (NautilusView *view) -{ - g_return_val_if_fail (NAUTILUS_IS_VIEW (view), NULL); - - return NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->get_backing_uri (view); -} - -/** - * nautilus_view_select_all: - * - * select all the items in the view - * - **/ -static void -nautilus_view_select_all (NautilusView *view) -{ - g_return_if_fail (NAUTILUS_IS_VIEW (view)); - - NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->select_all (view); -} - -static void -nautilus_view_select_first (NautilusView *view) -{ - g_return_if_fail (NAUTILUS_IS_VIEW (view)); - - NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->select_first (view); -} - -static void -nautilus_view_call_set_selection (NautilusView *view, GList *selection) -{ - g_return_if_fail (NAUTILUS_IS_VIEW (view)); - - NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->set_selection (view, selection); -} - -static GList * -nautilus_view_get_selection_for_file_transfer (NautilusView *view) -{ - g_return_val_if_fail (NAUTILUS_IS_VIEW (view), NULL); - - return NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->get_selection_for_file_transfer (view); -} - -static void -nautilus_view_invert_selection (NautilusView *view) -{ - g_return_if_fail (NAUTILUS_IS_VIEW (view)); - - NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->invert_selection (view); -} - -/** - * nautilus_view_reveal_selection: - * - * Scroll as necessary to reveal the selected items. - **/ -static void -nautilus_view_reveal_selection (NautilusView *view) -{ - g_return_if_fail (NAUTILUS_IS_VIEW (view)); - - NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->reveal_selection (view); -} - -static gboolean -nautilus_view_using_manual_layout (NautilusView *view) -{ - g_return_val_if_fail (NAUTILUS_IS_VIEW (view), FALSE); - - return NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->using_manual_layout (view); -} - -/** - * nautilus_view_get_icon: - * @view: a #NautilusView - * - * Retrieves the #GIcon that represents @view. - * - * Returns: (transfer none): the #Gicon that represents @view - */ -GIcon* -nautilus_view_get_icon (NautilusView *view) -{ - g_return_val_if_fail (NAUTILUS_IS_VIEW (view), NULL); - - return NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->get_icon (view); -} - -/** - * nautilus_view_get_view_widget: - * @view: a #NautilusView - * - * Retrieves the view menu, as a #GtkWidget. If it's %NULL, - * the button renders insensitive. - * - * Returns: (transfer none): a #GtkWidget for the view menu - */ -GtkWidget* -nautilus_view_get_view_widget (NautilusView *view) -{ - g_return_val_if_fail (NAUTILUS_IS_VIEW (view), NULL); - - return view->details->view_menu_widget; -} - -/** - * nautilus_view_can_rename_file - * - * Determine whether a file can be renamed. - * @file: A NautilusFile - * - * Return value: TRUE if @file can be renamed, FALSE otherwise. - * - **/ -static gboolean -nautilus_view_can_rename_file (NautilusView *view, NautilusFile *file) -{ - return NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->can_rename_file (view, file); -} - -static gboolean -nautilus_view_is_read_only (NautilusView *view) -{ - g_return_val_if_fail (NAUTILUS_IS_VIEW (view), FALSE); - - return NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->is_read_only (view); -} - -static gboolean -showing_trash_directory (NautilusView *view) -{ - NautilusFile *file; - - file = nautilus_view_get_directory_as_file (view); - if (file != NULL) { - return nautilus_file_is_in_trash (file); - } - return FALSE; -} - -static gboolean -showing_network_directory (NautilusView *view) -{ - NautilusFile *file; - - file = nautilus_view_get_directory_as_file (view); - if (file != NULL) { - return nautilus_file_is_in_network (file); - } - return FALSE; -} - -static gboolean -showing_recent_directory (NautilusView *view) -{ - NautilusFile *file; - - file = nautilus_view_get_directory_as_file (view); - if (file != NULL) { - return nautilus_file_is_in_recent (file); - } - return FALSE; -} - -static gboolean -nautilus_view_supports_creating_files (NautilusView *view) -{ - g_return_val_if_fail (NAUTILUS_IS_VIEW (view), FALSE); - - return !nautilus_view_is_read_only (view) - && !showing_trash_directory (view) - && !showing_recent_directory (view); -} - -static gboolean -nautilus_view_is_empty (NautilusView *view) -{ - g_return_val_if_fail (NAUTILUS_IS_VIEW (view), FALSE); - - return NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->is_empty (view); -} - -/** - * nautilus_view_bump_zoom_level: - * - * bump the current zoom level by invoking the relevant subclass through the slot - * - **/ -void -nautilus_view_bump_zoom_level (NautilusView *view, - int zoom_increment) -{ - g_return_if_fail (NAUTILUS_IS_VIEW (view)); - - if (!nautilus_view_supports_zooming (view)) { - return; - } - - NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->bump_zoom_level (view, zoom_increment); -} - -/** - * nautilus_view_can_zoom_in: - * - * Determine whether the view can be zoomed any closer. - * @view: The zoomable NautilusView. - * - * Return value: TRUE if @view can be zoomed any closer, FALSE otherwise. - * - **/ -gboolean -nautilus_view_can_zoom_in (NautilusView *view) -{ - g_return_val_if_fail (NAUTILUS_IS_VIEW (view), FALSE); - - if (!nautilus_view_supports_zooming (view)) { - return FALSE; - } - - return NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->can_zoom_in (view); -} - -/** - * nautilus_view_can_zoom_out: - * - * Determine whether the view can be zoomed any further away. - * @view: The zoomable NautilusView. - * - * Return value: TRUE if @view can be zoomed any further away, FALSE otherwise. - * - **/ -gboolean -nautilus_view_can_zoom_out (NautilusView *view) -{ - g_return_val_if_fail (NAUTILUS_IS_VIEW (view), FALSE); - - if (!nautilus_view_supports_zooming (view)) { - return FALSE; - } - - return NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->can_zoom_out (view); -} - -gboolean -nautilus_view_supports_zooming (NautilusView *view) -{ - g_return_val_if_fail (NAUTILUS_IS_VIEW (view), FALSE); - - return view->details->supports_zooming; -} - -/** - * nautilus_view_restore_default_zoom_level: - * - * restore to the default zoom level by invoking the relevant subclass through the slot - * - **/ -void -nautilus_view_restore_default_zoom_level (NautilusView *view) -{ - g_return_if_fail (NAUTILUS_IS_VIEW (view)); - - if (!nautilus_view_supports_zooming (view)) { - return; - } - - NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->restore_default_zoom_level (view); -} - -gboolean -nautilus_view_is_search (NautilusView *view) -{ - if (!view->details->model) - return FALSE; - - return NAUTILUS_IS_SEARCH_DIRECTORY (view->details->model); -} - -const char * -nautilus_view_get_view_id (NautilusView *view) -{ - return NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->get_view_id (view); -} - -char * -nautilus_view_get_first_visible_file (NautilusView *view) -{ - return NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->get_first_visible_file (view); -} - -void -nautilus_view_scroll_to_file (NautilusView *view, - const char *uri) -{ - NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->scroll_to_file (view, uri); -} - -/** - * nautilus_view_get_selection: - * - * Get a list of NautilusFile pointers that represents the - * currently-selected items in this view. Subclasses must override - * the signal handler for the 'get_selection' signal. Callers are - * responsible for g_free-ing the list (but not its data). - * @view: NautilusView whose selected items are of interest. - * - * Return value: GList of NautilusFile pointers representing the selection. - * - **/ -GList * -nautilus_view_get_selection (NautilusView *view) -{ - g_return_val_if_fail (NAUTILUS_IS_VIEW (view), NULL); - - return NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->get_selection (view); -} - -typedef struct { - NautilusFile *file; - NautilusView *directory_view; -} ScriptLaunchParameters; - -typedef struct { - NautilusFile *file; - NautilusView *directory_view; -} CreateTemplateParameters; - -static GList * -file_and_directory_list_to_files (GList *fad_list) -{ - GList *res, *l; - FileAndDirectory *fad; - - res = NULL; - for (l = fad_list; l != NULL; l = l->next) { - fad = l->data; - res = g_list_prepend (res, nautilus_file_ref (fad->file)); - } - return g_list_reverse (res); -} - - -static GList * -file_and_directory_list_from_files (NautilusDirectory *directory, GList *files) -{ - GList *res, *l; - FileAndDirectory *fad; - - res = NULL; - for (l = files; l != NULL; l = l->next) { - fad = g_new0 (FileAndDirectory, 1); - fad->directory = nautilus_directory_ref (directory); - fad->file = nautilus_file_ref (l->data); - res = g_list_prepend (res, fad); - } - return g_list_reverse (res); -} - -static void -file_and_directory_free (FileAndDirectory *fad) -{ - nautilus_directory_unref (fad->directory); - nautilus_file_unref (fad->file); - g_free (fad); -} - - -static void -file_and_directory_list_free (GList *list) -{ - GList *l; - - for (l = list; l != NULL; l = l->next) { - file_and_directory_free (l->data); - } - - g_list_free (list); -} - -static gboolean -file_and_directory_equal (gconstpointer v1, - gconstpointer v2) -{ - const FileAndDirectory *fad1, *fad2; - fad1 = v1; - fad2 = v2; - - return (fad1->file == fad2->file && - fad1->directory == fad2->directory); -} - -static guint -file_and_directory_hash (gconstpointer v) -{ - const FileAndDirectory *fad; - - fad = v; - return GPOINTER_TO_UINT (fad->file) ^ GPOINTER_TO_UINT (fad->directory); -} - -static ScriptLaunchParameters * -script_launch_parameters_new (NautilusFile *file, - NautilusView *directory_view) -{ - ScriptLaunchParameters *result; - - result = g_new0 (ScriptLaunchParameters, 1); - g_object_ref (directory_view); - result->directory_view = directory_view; - nautilus_file_ref (file); - result->file = file; - - return result; -} - -static void -script_launch_parameters_free (ScriptLaunchParameters *parameters) -{ - g_object_unref (parameters->directory_view); - nautilus_file_unref (parameters->file); - g_free (parameters); -} - -static CreateTemplateParameters * -create_template_parameters_new (NautilusFile *file, - NautilusView *directory_view) -{ - CreateTemplateParameters *result; - - result = g_new0 (CreateTemplateParameters, 1); - g_object_ref (directory_view); - result->directory_view = directory_view; - nautilus_file_ref (file); - result->file = file; - - return result; -} - -static void -create_templates_parameters_free (CreateTemplateParameters *parameters) -{ - g_object_unref (parameters->directory_view); - nautilus_file_unref (parameters->file); - g_free (parameters); -} - -NautilusWindow * -nautilus_view_get_window (NautilusView *view) -{ - return nautilus_window_slot_get_window (view->details->slot); -} - -NautilusWindowSlot * -nautilus_view_get_nautilus_window_slot (NautilusView *view) -{ - g_assert (view->details->slot != NULL); - - return view->details->slot; -} - -/* Returns the GtkWindow that this directory view occupies, or NULL - * if at the moment this directory view is not in a GtkWindow or the - * GtkWindow cannot be determined. Primarily used for parenting dialogs. - */ -static GtkWindow * -nautilus_view_get_containing_window (NautilusView *view) -{ - GtkWidget *window; - - g_assert (NAUTILUS_IS_VIEW (view)); - - window = gtk_widget_get_ancestor (GTK_WIDGET (view), GTK_TYPE_WINDOW); - if (window == NULL) { - return NULL; - } - - return GTK_WINDOW (window); -} - -static gboolean -nautilus_view_confirm_multiple (GtkWindow *parent_window, - int count, - gboolean tabs) -{ - GtkDialog *dialog; - char *prompt; - char *detail; - int response; - - if (count <= SILENT_WINDOW_OPEN_LIMIT) { - return TRUE; - } - - prompt = _("Are you sure you want to open all files?"); - if (tabs) { - detail = g_strdup_printf (ngettext("This will open %'d separate tab.", - "This will open %'d separate tabs.", count), count); - } else { - detail = g_strdup_printf (ngettext("This will open %'d separate window.", - "This will open %'d separate windows.", count), count); - } - dialog = eel_show_yes_no_dialog (prompt, detail, - _("_OK"), _("_Cancel"), - parent_window); - g_free (detail); - - response = gtk_dialog_run (dialog); - gtk_widget_destroy (GTK_WIDGET (dialog)); - - return response == GTK_RESPONSE_YES; -} - -static gboolean -selection_not_empty_in_menu_callback (NautilusView *view, GList *selection) -{ - if (selection != NULL) { - return TRUE; - } - - return FALSE; -} - -static char * -get_view_directory (NautilusView *view) -{ - char *uri, *path; - GFile *f; - - uri = nautilus_directory_get_uri (view->details->model); - if (eel_uri_is_desktop (uri)) { - g_free (uri); - uri = nautilus_get_desktop_directory_uri (); - - } - f = g_file_new_for_uri (uri); - path = g_file_get_path (f); - g_object_unref (f); - g_free (uri); - - return path; -} - -void -nautilus_view_preview_files (NautilusView *view, - GList *files, - GArray *locations) -{ - gchar *uri; - guint xid; - GtkWidget *toplevel; - - uri = nautilus_file_get_uri (files->data); - toplevel = gtk_widget_get_toplevel (GTK_WIDGET (view)); - - xid = gdk_x11_window_get_xid (gtk_widget_get_window (toplevel)); - nautilus_previewer_call_show_file (uri, xid, TRUE); - - g_free (uri); -} - -void -nautilus_view_activate_selection (NautilusView *view) -{ - GList *selection; - - selection = nautilus_view_get_selection (view); - nautilus_view_activate_files (view, - selection, - 0, - TRUE); - nautilus_file_list_free (selection); -} - -void -nautilus_view_activate_files (NautilusView *view, - GList *files, - NautilusWindowOpenFlags flags, - gboolean confirm_multiple) -{ - char *path; - - path = get_view_directory (view); - nautilus_mime_activate_files (nautilus_view_get_containing_window (view), - view->details->slot, - files, - path, - flags, - confirm_multiple); - - g_free (path); -} - -static void -nautilus_view_activate_file (NautilusView *view, - NautilusFile *file, - NautilusWindowOpenFlags flags) -{ - char *path; - - path = get_view_directory (view); - nautilus_mime_activate_file (nautilus_view_get_containing_window (view), - view->details->slot, - file, - path, - flags); - - g_free (path); -} - -static void -action_open_with_default_application (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - NautilusView *view; - - view = NAUTILUS_VIEW (user_data); - nautilus_view_activate_selection (view); -} -static void -action_open_file_and_close_window (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - GList *selection; - NautilusView *view; - - view = NAUTILUS_VIEW (user_data); - - selection = nautilus_view_get_selection (view); - nautilus_view_activate_files (view, - selection, - NAUTILUS_WINDOW_OPEN_FLAG_CLOSE_BEHIND, - TRUE); - nautilus_file_list_free (selection); -} - -static void -got_it_clicked (GtkDialog *dialog, - gint response_id, - gpointer user_data) -{ - g_settings_set_boolean (nautilus_preferences, - NAUTILUS_PREFERENCES_SHOW_MOVE_TO_TRASH_SHORTCUT_CHANGED_DIALOG, - FALSE); -} - -static void -action_show_move_to_trash_shortcut_changed_dialog (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - NautilusView *view; - GtkWindow *dialog; - GtkBuilder *builder; - gboolean show_dialog_preference; - - view = NAUTILUS_VIEW (user_data); - show_dialog_preference = g_settings_get_boolean (nautilus_preferences, - NAUTILUS_PREFERENCES_SHOW_MOVE_TO_TRASH_SHORTCUT_CHANGED_DIALOG); - if (show_dialog_preference) { - builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/nautilus-move-to-trash-shortcut-changed.ui"); - dialog = GTK_WINDOW (gtk_builder_get_object (builder, "move_to_trash_shortcut_changed_dialog")); - - gtk_window_set_transient_for (dialog, GTK_WINDOW (nautilus_view_get_window (view))); - g_signal_connect (dialog, "response", - G_CALLBACK (got_it_clicked), - view); - - gtk_widget_show (GTK_WIDGET (dialog)); - gtk_dialog_run(GTK_DIALOG (dialog)); - gtk_widget_destroy (GTK_WIDGET (dialog)); - - g_object_unref (builder); - } -} -static void -action_open_item_location (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - NautilusView *view; - GList *selection; - NautilusFile *item; - GFile *activation_location; - NautilusFile *activation_file; - NautilusFile *location; - - view = NAUTILUS_VIEW (user_data); - selection = nautilus_view_get_selection (view); - - if (!selection) - return; - - item = NAUTILUS_FILE (selection->data); - activation_location = nautilus_file_get_activation_location (item); - activation_file = nautilus_file_get (activation_location); - location = nautilus_file_get_parent (activation_file); - - nautilus_view_activate_file (view, location, 0); - - nautilus_file_unref (location); - nautilus_file_unref (activation_file); - g_object_unref (activation_location); - nautilus_file_list_free (selection); -} - -static void -action_open_item_new_tab (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - NautilusView *view; - GList *selection; - GtkWindow *window; - - view = NAUTILUS_VIEW (user_data); - selection = nautilus_view_get_selection (view); - - window = nautilus_view_get_containing_window (view); - - if (nautilus_view_confirm_multiple (window, g_list_length (selection), TRUE)) { - nautilus_view_activate_files (view, - selection, - NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB, - FALSE); - } - - nautilus_file_list_free (selection); -} - -static void -app_chooser_dialog_response_cb (GtkDialog *dialog, - gint response_id, - gpointer user_data) -{ - GtkWindow *parent_window; - GList *files; - GAppInfo *info; - - parent_window = user_data; - files = g_object_get_data (G_OBJECT (dialog), "directory-view:files"); - - if (response_id != GTK_RESPONSE_OK) - goto out; - - info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (dialog)); - - g_signal_emit_by_name (nautilus_signaller_get_current (), "mime-data-changed"); - - nautilus_launch_application (info, files, parent_window); - - g_object_unref (info); -out: - gtk_widget_destroy (GTK_WIDGET (dialog)); -} - -static void -choose_program (NautilusView *view, - GList *files) -{ - GtkWidget *dialog; - gchar *mime_type; - GtkWindow *parent_window; - - g_assert (NAUTILUS_IS_VIEW (view)); - - mime_type = nautilus_file_get_mime_type (files->data); - parent_window = nautilus_view_get_containing_window (view); - - dialog = gtk_app_chooser_dialog_new_for_content_type (parent_window, - GTK_DIALOG_MODAL | - GTK_DIALOG_DESTROY_WITH_PARENT | - GTK_DIALOG_USE_HEADER_BAR, - mime_type); - g_object_set_data_full (G_OBJECT (dialog), - "directory-view:files", - files, - (GDestroyNotify) nautilus_file_list_free); - gtk_widget_show (dialog); - - g_signal_connect_object (dialog, "response", - G_CALLBACK (app_chooser_dialog_response_cb), - parent_window, 0); -} - -static void -open_with_other_program (NautilusView *view) -{ - GList *selection; - - g_assert (NAUTILUS_IS_VIEW (view)); - - selection = nautilus_view_get_selection (view); - choose_program (view, selection); -} - -static void -action_open_with_other_application (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - g_assert (NAUTILUS_IS_VIEW (user_data)); - - open_with_other_program (NAUTILUS_VIEW (user_data)); -} - -static void -trash_or_delete_selected_files (NautilusView *view) -{ - GList *selection; - - /* This might be rapidly called multiple times for the same selection - * when using keybindings. So we remember if the current selection - * was already removed (but the view doesn't know about it yet). - */ - if (!view->details->selection_was_removed) { - selection = nautilus_view_get_selection_for_file_transfer (view); - trash_or_delete_files (nautilus_view_get_containing_window (view), - selection, - view); - nautilus_file_list_free (selection); - view->details->selection_was_removed = TRUE; - } -} - -static void -action_move_to_trash (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - trash_or_delete_selected_files (NAUTILUS_VIEW (user_data)); -} - -static void -action_remove_from_recent (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - /* TODO:implement a set of functions for this, is very confusing to - * call trash_or_delete_file to remove from recent, even if it does like - * that not deleting/moving the files to trash */ - trash_or_delete_selected_files (NAUTILUS_VIEW (user_data)); -} - -static void -delete_selected_files (NautilusView *view) -{ - GList *selection; - GList *node; - GList *locations; - - selection = nautilus_view_get_selection_for_file_transfer (view); - if (selection == NULL) { - return; - } - - locations = NULL; - for (node = selection; node != NULL; node = node->next) { - locations = g_list_prepend (locations, - nautilus_file_get_location ((NautilusFile *) node->data)); - } - locations = g_list_reverse (locations); - - nautilus_file_operations_delete (locations, nautilus_view_get_containing_window (view), NULL, NULL); - - g_list_free_full (locations, g_object_unref); - nautilus_file_list_free (selection); -} - -static void -action_delete (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - delete_selected_files (NAUTILUS_VIEW (user_data)); -} - -static void -action_restore_from_trash (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - NautilusView *view; - GList *selection; - - view = NAUTILUS_VIEW (user_data); - - selection = nautilus_view_get_selection_for_file_transfer (view); - nautilus_restore_files_from_trash (selection, - nautilus_view_get_containing_window (view)); - - nautilus_file_list_free (selection); - -} - -static void -action_select_all (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - NautilusView *view; - - g_assert (NAUTILUS_IS_VIEW (user_data)); - - view = NAUTILUS_VIEW (user_data); - - nautilus_view_select_all (view); -} - -static void -action_invert_selection (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - g_assert (NAUTILUS_IS_VIEW (user_data)); - - nautilus_view_invert_selection (user_data); -} - -static void -pattern_select_response_cb (GtkWidget *dialog, int response, gpointer user_data) -{ - NautilusView *view; - NautilusDirectory *directory; - GtkWidget *entry; - GList *selection; - - view = NAUTILUS_VIEW (user_data); - - switch (response) { - case GTK_RESPONSE_OK : - entry = g_object_get_data (G_OBJECT (dialog), "entry"); - directory = nautilus_view_get_model (view); - selection = nautilus_directory_match_pattern (directory, - gtk_entry_get_text (GTK_ENTRY (entry))); - - if (selection) { - nautilus_view_call_set_selection (view, selection); - nautilus_file_list_free (selection); - - nautilus_view_reveal_selection(view); - } - /* fall through */ - case GTK_RESPONSE_NONE : - case GTK_RESPONSE_DELETE_EVENT : - case GTK_RESPONSE_CANCEL : - gtk_widget_destroy (GTK_WIDGET (dialog)); - break; - default : - g_assert_not_reached (); - } -} - -static void -select_pattern (NautilusView *view) -{ - GtkWidget *dialog; - GtkWidget *label; - GtkWidget *example; - GtkWidget *grid; - GtkWidget *entry; - char *example_pattern; - - dialog = gtk_dialog_new_with_buttons (_("Select Items Matching"), - nautilus_view_get_containing_window (view), - GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_USE_HEADER_BAR, - _("_Cancel"), - GTK_RESPONSE_CANCEL, - _("_Select"), - GTK_RESPONSE_OK, - NULL); - gtk_dialog_set_default_response (GTK_DIALOG (dialog), - GTK_RESPONSE_OK); - gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); - gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 2); - - label = gtk_label_new_with_mnemonic (_("_Pattern:")); - gtk_widget_set_halign (label, GTK_ALIGN_START); - - example = gtk_label_new (NULL); - gtk_widget_set_halign (example, GTK_ALIGN_START); - example_pattern = g_strdup_printf ("%s<i>%s</i> ", - _("Examples: "), - "*.png, file\?\?.txt, pict*.\?\?\?"); - gtk_label_set_markup (GTK_LABEL (example), example_pattern); - g_free (example_pattern); - - entry = gtk_entry_new (); - gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE); - gtk_widget_set_hexpand (entry, TRUE); - - grid = gtk_grid_new (); - g_object_set (grid, - "orientation", GTK_ORIENTATION_VERTICAL, - "border-width", 6, - "row-spacing", 6, - "column-spacing", 12, - NULL); - - gtk_container_add (GTK_CONTAINER (grid), label); - gtk_grid_attach_next_to (GTK_GRID (grid), entry, label, - GTK_POS_RIGHT, 1, 1); - gtk_grid_attach_next_to (GTK_GRID (grid), example, entry, - GTK_POS_BOTTOM, 1, 1); - - gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry); - gtk_widget_show_all (grid); - gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), grid); - g_object_set_data (G_OBJECT (dialog), "entry", entry); - g_signal_connect (dialog, "response", - G_CALLBACK (pattern_select_response_cb), - view); - gtk_widget_show_all (dialog); -} - -static void -action_select_pattern (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - g_assert (NAUTILUS_IS_VIEW (user_data)); - - select_pattern(user_data); -} - -static void -zoom_level_changed (GtkRange *range, - NautilusView *view) -{ - g_action_group_change_action_state (view->details->view_action_group, - "zoom-to-level", - g_variant_new_int32 (gtk_range_get_value (range))); -} - -static void -reveal_newly_added_folder (NautilusView *view, NautilusFile *new_file, - NautilusDirectory *directory, GFile *target_location) -{ - GFile *location; - - location = nautilus_file_get_location (new_file); - if (g_file_equal (location, target_location)) { - g_signal_handlers_disconnect_by_func (view, - G_CALLBACK (reveal_newly_added_folder), - (void *) target_location); - nautilus_view_select_file (view, new_file); - } - g_object_unref (location); -} - -typedef struct { - NautilusView *directory_view; - GHashTable *added_locations; - GList *selection; -} NewFolderData; - -typedef struct { - NautilusView *directory_view; - GHashTable *to_remove_locations; - NautilusFile *new_folder; -} NewFolderSelectionData; - -static void -track_newly_added_locations (NautilusView *view, NautilusFile *new_file, - NautilusDirectory *directory, gpointer user_data) -{ - NewFolderData *data; - - data = user_data; - - g_hash_table_insert (data->added_locations, nautilus_file_get_location (new_file), NULL); -} - -static void -new_folder_done (GFile *new_folder, - gboolean success, - gpointer user_data) -{ - NautilusView *directory_view; - NautilusFile *file; - char screen_string[32]; - GdkScreen *screen; - NewFolderData *data; - - data = (NewFolderData *)user_data; - - directory_view = data->directory_view; - - if (directory_view == NULL) { - goto fail; - } - - g_signal_handlers_disconnect_by_func (directory_view, - G_CALLBACK (track_newly_added_locations), - (void *) data); - - if (new_folder == NULL) { - goto fail; - } - - screen = gtk_widget_get_screen (GTK_WIDGET (directory_view)); - g_snprintf (screen_string, sizeof (screen_string), "%d", gdk_screen_get_number (screen)); - - - file = nautilus_file_get (new_folder); - nautilus_file_set_metadata - (file, NAUTILUS_METADATA_KEY_SCREEN, - NULL, - screen_string); - - if (data->selection != NULL) { - NewFolderSelectionData *sdata; - GList *uris, *l; - char *target_uri; - - sdata = g_new (NewFolderSelectionData, 1); - sdata->directory_view = directory_view; - sdata->to_remove_locations = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, - g_object_unref, NULL); - sdata->new_folder = g_object_ref (file); - - uris = NULL; - for (l = data->selection; l != NULL; l = l->next) { - GFile *old_location; - GFile *new_location; - char *basename; - - uris = g_list_prepend (uris, nautilus_file_get_uri ((NautilusFile *) l->data)); - - old_location = nautilus_file_get_location (l->data); - basename = g_file_get_basename (old_location); - new_location = g_file_resolve_relative_path (new_folder, basename); - g_hash_table_insert (sdata->to_remove_locations, new_location, NULL); - g_free (basename); - g_object_unref (old_location); - } - uris = g_list_reverse (uris); - - target_uri = nautilus_file_get_uri (file); - - nautilus_view_move_copy_items (directory_view, - uris, - NULL, - target_uri, - GDK_ACTION_MOVE, - 0, 0); - g_list_free_full (uris, g_free); - g_free (target_uri); - } else { - if (g_hash_table_lookup_extended (data->added_locations, new_folder, NULL, NULL)) { - /* The file was already added */ - nautilus_view_select_file (directory_view, file); - } else { - /* We need to run after the default handler adds the folder we want to - * operate on. The ADD_FILE signal is registered as G_SIGNAL_RUN_LAST, so we - * must use connect_after. - */ - g_signal_connect_data (directory_view, - "add-file", - G_CALLBACK (reveal_newly_added_folder), - g_object_ref (new_folder), - (GClosureNotify)g_object_unref, - G_CONNECT_AFTER); - } - } - - nautilus_file_unref (file); - - fail: - g_hash_table_destroy (data->added_locations); - - if (data->directory_view != NULL) { - g_object_remove_weak_pointer (G_OBJECT (data->directory_view), - (gpointer *) &data->directory_view); - } - - nautilus_file_list_free (data->selection); - g_free (data); -} - - -static NewFolderData * -new_folder_data_new (NautilusView *directory_view, - gboolean with_selection) -{ - NewFolderData *data; - - data = g_new (NewFolderData, 1); - data->directory_view = directory_view; - data->added_locations = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, - g_object_unref, NULL); - if (with_selection) { - data->selection = nautilus_view_get_selection_for_file_transfer (directory_view); - } else { - data->selection = NULL; - } - g_object_add_weak_pointer (G_OBJECT (data->directory_view), - (gpointer *) &data->directory_view); - - return data; -} - -static GdkPoint * -context_menu_to_file_operation_position (NautilusView *view) -{ - g_return_val_if_fail (NAUTILUS_IS_VIEW (view), NULL); - - if (nautilus_view_using_manual_layout (view) - && view->details->context_menu_position.x >= 0 - && view->details->context_menu_position.y >= 0) { - NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->widget_to_file_operation_position - (view, &view->details->context_menu_position); - return &view->details->context_menu_position; - } else { - return NULL; - } -} - -typedef struct { - NautilusView *view; - GtkWidget *widget; - GtkWidget *error_label; - GtkWidget *name_entry; - GtkWidget *activate_button; - gboolean target_is_folder; - NautilusFile *target_file; - gboolean duplicated_is_folder; - void (*on_name_accepted) (gpointer data); - /* For create folder only */ - gboolean with_selection; -} FileNameWidgetData; - -static gboolean -duplicated_file_label_show (FileNameWidgetData *data) -{ - if (data->duplicated_is_folder) - gtk_label_set_label (GTK_LABEL (data->error_label), _("A folder with that name already exists.")); - else - gtk_label_set_label (GTK_LABEL (data->error_label), _("A file with that name already exists.")); - - data->view->details->duplicated_label_timeout_id = 0; - - return G_SOURCE_REMOVE; -} - -static gchar* -validate_file_name (const gchar *name, - gboolean is_folder) -{ - gchar *error_message = NULL; - - if (strstr (name, "/") != NULL) { - if (is_folder) - error_message = _("Folder names cannot contain “/”."); - else - error_message = _("Files names cannot contain “/”."); - } else if (strcmp (name, ".") == 0){ - if (is_folder) - error_message = _("A folder can not be called “.”."); - else - error_message = _("A file can not be called “.”."); - } else if (strcmp (name, "..") == 0){ - if (is_folder) - error_message = _("A folder can not be called “..”."); - else - error_message = _("A file can not be called “..”."); - } - - return error_message; -} - -static void -file_name_widget_entry_on_changed (gpointer user_data) -{ - FileNameWidgetData *data; - NautilusFile *existing_file; - gchar *name; - gchar *error_message; - gboolean valid_name; - gboolean duplicated; - - data = (FileNameWidgetData *) user_data; - name = g_strstrip (g_strdup (gtk_entry_get_text (GTK_ENTRY (data->name_entry)))); - error_message = validate_file_name (name, TRUE); - gtk_label_set_label (GTK_LABEL (data->error_label), error_message); - - existing_file = nautilus_directory_get_file_by_name (data->view->details->model, name); - - valid_name = strlen (name) > 0 && error_message == NULL; - /* If there is a target file and the name is the same, we don't show it - * as duplicated. This is the case for renaming. */ - duplicated = existing_file != NULL && - (data->target_file == NULL || - nautilus_file_compare_display_name (data->target_file, name) != 0); - gtk_widget_set_sensitive (data->activate_button, valid_name && !duplicated); - - if (data->view->details->duplicated_label_timeout_id > 0) { - g_source_remove (data->view->details->duplicated_label_timeout_id); - data->view->details->duplicated_label_timeout_id = 0; - } - - /* Report duplicated file only if not other message shown (for instance, - * folders like "." or ".." will always exists, but we consider it as an - * error, not as a duplicated file or if the name is the same as the file - * we are renaming also don't report as a duplicated */ - if (duplicated && valid_name) { - data->duplicated_is_folder = nautilus_file_is_directory (existing_file); - data->view->details->duplicated_label_timeout_id = - g_timeout_add (FILE_NAME_DUPLICATED_LABEL_TIMEOUT, - (GSourceFunc)duplicated_file_label_show, - data); - } - - if (existing_file != NULL) - nautilus_file_unref (existing_file); - - g_free (name); -} - -static void -create_folder_dialog_on_response (GtkDialog *dialog, - gint response_id, - gpointer user_data) -{ - FileNameWidgetData *widget_data; - - widget_data = (FileNameWidgetData *) user_data; - - if (response_id == GTK_RESPONSE_OK) { - NewFolderData *data; - GdkPoint *pos; - char *parent_uri; - gchar *name; - - data = new_folder_data_new (widget_data->view, widget_data->with_selection); - - name = g_strstrip (g_strdup (gtk_entry_get_text (GTK_ENTRY (widget_data->name_entry)))); - g_signal_connect_data (widget_data->view, - "add-file", - G_CALLBACK (track_newly_added_locations), - data, - (GClosureNotify)NULL, - G_CONNECT_AFTER); - - pos = context_menu_to_file_operation_position (widget_data->view); - - parent_uri = nautilus_view_get_backing_uri (widget_data->view); - nautilus_file_operations_new_folder (GTK_WIDGET (widget_data->view), - pos, parent_uri, name, - new_folder_done, data); - - g_free (parent_uri); - g_free (name); - } - - gtk_widget_destroy (GTK_WIDGET (dialog)); - g_free (user_data); -} - - -static void -create_folder_on_name_accepted (gpointer user_data) -{ - FileNameWidgetData *data; - - data = (FileNameWidgetData *) user_data; - gtk_dialog_response (GTK_DIALOG (data->widget), - GTK_RESPONSE_OK); -} - -static void -rename_file_on_name_accepted (gpointer user_data) -{ - FileNameWidgetData *data; - gchar *name; - - data = (FileNameWidgetData *) user_data; - - name = g_strstrip (g_strdup (gtk_entry_get_text (GTK_ENTRY (data->name_entry)))); - nautilus_rename_file (data->target_file, name, NULL, NULL); - - nautilus_view_select_file (data->view, data->target_file); - nautilus_view_reveal_selection (data->view); - - gtk_widget_hide (data->widget); - - g_free (name); -} - -static void -file_name_widget_on_activate (gpointer user_data) -{ - FileNameWidgetData *data; - NautilusFile *existing_file; - gchar *name; - gchar *error_message; - gboolean valid_name; - gboolean duplicated; - - data = (FileNameWidgetData *) user_data; - name = g_strstrip (g_strdup (gtk_entry_get_text (GTK_ENTRY (data->name_entry)))); - existing_file = nautilus_directory_get_file_by_name (data->view->details->model, name); - error_message = validate_file_name (name, TRUE); - valid_name = strlen (name) > 0 && error_message == NULL; - duplicated = existing_file != NULL && - (data->target_file == NULL || - nautilus_file_compare_display_name (data->target_file, name) != 0); - - if (data->view->details->duplicated_label_timeout_id > 0) { - g_source_remove (data->view->details->duplicated_label_timeout_id); - data->view->details->duplicated_label_timeout_id = 0; - } - - if (valid_name && !duplicated) { - data->on_name_accepted ((gpointer) data); - } else { - /* Report duplicated file only if not other message shown (for instance, - * folders like "." or ".." will always exists, but we consider it as an - * error, not as a duplicated file) */ - if (existing_file != NULL && valid_name) { - data->duplicated_is_folder = nautilus_file_is_directory (existing_file); - /* Show it inmediatily since the user tried to trigger the action */ - duplicated_file_label_show (data); - } - } - - if (existing_file != NULL) - nautilus_file_unref (existing_file); - - g_free (name); -} - -static void -rename_file_popover_on_closed (GtkPopover *popover, - gpointer user_data) -{ - FileNameWidgetData *widget_data; - - widget_data = (FileNameWidgetData *) user_data; - widget_data->view->details->rename_file_popover = NULL; - g_free (widget_data); -} - -static GdkRectangle* -nautilus_view_compute_rename_popover_relative_to (NautilusView *view) -{ - return NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->compute_rename_popover_relative_to (view); -} - -static void -nautilus_view_rename_file_popover_new (NautilusView *view, - NautilusFile *target_file) -{ - FileNameWidgetData *widget_data; - GtkWidget *label_file_name; - GtkBuilder *builder; - gint start_offset, end_offset; - GdkRectangle *relative_to; - - if (view->details->rename_file_popover != NULL) - return; - - builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/nautilus-rename-file-popover.ui"); - label_file_name = GTK_WIDGET (gtk_builder_get_object (builder, "name_label")); - - widget_data = g_new (FileNameWidgetData, 1); - widget_data->view = view; - widget_data->on_name_accepted = rename_file_on_name_accepted; - widget_data->widget = GTK_WIDGET (gtk_builder_get_object (builder, "rename_file_popover")); - widget_data->activate_button = GTK_WIDGET (gtk_builder_get_object (builder, "rename_button")); - widget_data->error_label = GTK_WIDGET (gtk_builder_get_object (builder, "error_label")); - widget_data->name_entry = GTK_WIDGET (gtk_builder_get_object (builder, "name_entry")); - widget_data->target_is_folder = nautilus_file_is_directory (target_file); - widget_data->target_file = target_file; - - view->details->rename_file_popover = widget_data->widget; - - /* Connect signals */ - gtk_builder_add_callback_symbols (builder, - "file_name_widget_entry_on_changed", - G_CALLBACK (file_name_widget_entry_on_changed), - "file_name_widget_on_activate", - G_CALLBACK (file_name_widget_on_activate), - "rename_file_popover_on_closed", - G_CALLBACK (rename_file_popover_on_closed), - "rename_file_popover_on_unmap", - G_CALLBACK (gtk_widget_destroy), - NULL); - - gtk_builder_connect_signals (builder, widget_data); - - if (widget_data->target_is_folder) - gtk_label_set_text (GTK_LABEL (label_file_name), _("Folder name")); - else - gtk_label_set_text (GTK_LABEL (label_file_name), _("File name")); - gtk_entry_set_text (GTK_ENTRY (widget_data->name_entry), nautilus_file_get_name (target_file)); - - relative_to = nautilus_view_compute_rename_popover_relative_to (view); - gtk_popover_set_default_widget (GTK_POPOVER (widget_data->widget), - widget_data->activate_button); - gtk_popover_set_pointing_to (GTK_POPOVER (widget_data->widget), relative_to); - gtk_popover_set_relative_to (GTK_POPOVER (widget_data->widget), - GTK_WIDGET (view)); - gtk_widget_show (widget_data->widget); - gtk_widget_grab_focus (widget_data->widget); - - /* Select the name part withouth the file extension */ - eel_filename_get_rename_region (nautilus_file_get_name (target_file), - &start_offset, &end_offset); - gtk_editable_select_region (GTK_EDITABLE (widget_data->name_entry), - start_offset, end_offset); - - /* Update the rename button status */ - file_name_widget_entry_on_changed (widget_data); - - - g_object_unref (builder); -} - -static void -nautilus_view_new_folder_dialog_new (NautilusView *view, - gboolean with_selection) -{ - FileNameWidgetData *widget_data; - GtkWidget *label_file_name; - GtkBuilder *builder; - - builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/nautilus-create-folder-dialog.ui"); - label_file_name = GTK_WIDGET (gtk_builder_get_object (builder, "name_label")); - - widget_data = g_new (FileNameWidgetData, 1); - widget_data->view = view; - widget_data->on_name_accepted = create_folder_on_name_accepted; - widget_data->widget = GTK_WIDGET (gtk_builder_get_object (builder, "create_folder_dialog")); - widget_data->activate_button = GTK_WIDGET (gtk_builder_get_object (builder, "ok_button")); - widget_data->error_label = GTK_WIDGET (gtk_builder_get_object (builder, "error_label")); - widget_data->name_entry = GTK_WIDGET (gtk_builder_get_object (builder, "name_entry")); - widget_data->target_is_folder = TRUE; - widget_data->target_file = NULL; - widget_data->with_selection = with_selection; - - gtk_window_set_transient_for (GTK_WINDOW (widget_data->widget), - GTK_WINDOW (nautilus_view_get_window (view))); - - /* Connect signals */ - gtk_builder_add_callback_symbols (builder, - "file_name_widget_entry_on_changed", - G_CALLBACK (file_name_widget_entry_on_changed), - "file_name_widget_on_activate", - G_CALLBACK (file_name_widget_on_activate), - "create_folder_dialog_on_response", - G_CALLBACK (create_folder_dialog_on_response), - NULL); - - gtk_builder_connect_signals (builder, widget_data); - gtk_button_set_label (GTK_BUTTON (widget_data->activate_button), - _("Create")); - gtk_label_set_text (GTK_LABEL (label_file_name), _("Folder name")); - gtk_window_set_title (GTK_WINDOW (widget_data->widget), _("New Folder")); - - gtk_widget_show_all (widget_data->widget); - /* Update the ok button status */ - file_name_widget_entry_on_changed (widget_data); - - g_object_unref (builder); -} - -static void -nautilus_view_new_folder (NautilusView *directory_view, - gboolean with_selection) -{ - nautilus_view_new_folder_dialog_new (directory_view, with_selection); -} - -static NewFolderData * -setup_new_folder_data (NautilusView *directory_view) -{ - NewFolderData *data; - - data = new_folder_data_new (directory_view, FALSE); - - g_signal_connect_data (directory_view, - "add-file", - G_CALLBACK (track_newly_added_locations), - data, - (GClosureNotify)NULL, - G_CONNECT_AFTER); - - return data; -} - -void -nautilus_view_new_file_with_initial_contents (NautilusView *view, - const char *parent_uri, - const char *filename, - const char *initial_contents, - int length, - GdkPoint *pos) -{ - NewFolderData *data; - - g_assert (parent_uri != NULL); - - data = setup_new_folder_data (view); - - if (pos == NULL) { - pos = context_menu_to_file_operation_position (view); - } - - nautilus_file_operations_new_file (GTK_WIDGET (view), - pos, parent_uri, filename, - initial_contents, length, - new_folder_done, data); -} - -static void -nautilus_view_new_file (NautilusView *directory_view, - const char *parent_uri, - NautilusFile *source) -{ - GdkPoint *pos; - NewFolderData *data; - char *source_uri; - char *container_uri; - - container_uri = NULL; - if (parent_uri == NULL) { - container_uri = nautilus_view_get_backing_uri (directory_view); - g_assert (container_uri != NULL); - } - - if (source == NULL) { - nautilus_view_new_file_with_initial_contents (directory_view, - parent_uri != NULL ? parent_uri : container_uri, - NULL, - NULL, - 0, - NULL); - g_free (container_uri); - return; - } - - g_return_if_fail (nautilus_file_is_local (source)); - - pos = context_menu_to_file_operation_position (directory_view); - - data = setup_new_folder_data (directory_view); - - source_uri = nautilus_file_get_uri (source); - - nautilus_file_operations_new_file_from_template (GTK_WIDGET (directory_view), - pos, - parent_uri != NULL ? parent_uri : container_uri, - NULL, - source_uri, - new_folder_done, data); - - g_free (source_uri); - g_free (container_uri); -} - -static void -action_new_folder (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - g_assert (NAUTILUS_IS_VIEW (user_data)); - - nautilus_view_new_folder (NAUTILUS_VIEW (user_data), FALSE); -} - -static void -action_new_folder_with_selection (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - g_assert (NAUTILUS_IS_VIEW (user_data)); - - nautilus_view_new_folder (NAUTILUS_VIEW (user_data), TRUE); -} - -static void -action_properties (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - NautilusView *view; - GList *selection; - GList *files; - - g_assert (NAUTILUS_IS_VIEW (user_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) { - files = g_list_append (NULL, nautilus_file_ref (view->details->directory_as_file)); - - nautilus_properties_window_present (files, GTK_WIDGET (view), NULL); - - nautilus_file_list_free (files); - } - } else { - nautilus_properties_window_present (selection, GTK_WIDGET (view), NULL); - } - nautilus_file_list_free (selection); -} - -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; - - g_settings_set_boolean (gtk_filechooser_preferences, - NAUTILUS_PREFERENCES_SHOW_HIDDEN_FILES, - show_hidden); - - if (view->details->model != NULL) { - load_directory (view, view->details->model); - } - } -} - -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 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); -} - -static void -action_zoom_default (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - nautilus_view_restore_default_zoom_level (user_data); -} - -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 -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 -click_policy_changed_callback (gpointer callback_data) -{ - NautilusView *view; - - view = NAUTILUS_VIEW (callback_data); - - NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->click_policy_changed (view); -} - -gboolean -nautilus_view_should_sort_directories_first (NautilusView *view) -{ - return view->details->sort_directories_first; -} - -static void -sort_directories_first_changed_callback (gpointer callback_data) -{ - NautilusView *view; - gboolean preference_value; - - view = NAUTILUS_VIEW (callback_data); - - preference_value = - g_settings_get_boolean (nautilus_preferences, NAUTILUS_PREFERENCES_SORT_DIRECTORIES_FIRST); - - if (preference_value != view->details->sort_directories_first) { - view->details->sort_directories_first = preference_value; - NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->sort_directories_first_changed (view); - } -} - -static void -show_hidden_files_changed_callback (gpointer callback_data) -{ - NautilusView *view; - gboolean preference_value; - - view = NAUTILUS_VIEW (callback_data); - - preference_value = - g_settings_get_boolean (gtk_filechooser_preferences, NAUTILUS_PREFERENCES_SHOW_HIDDEN_FILES); - - nautilus_view_set_show_hidden_files (view, preference_value); -} - -static gboolean -set_up_scripts_directory_global (void) -{ - char *old_scripts_directory_path; - char *scripts_directory_path; - const char *override; - - if (scripts_directory_uri != NULL) { - return TRUE; - } - - scripts_directory_path = nautilus_get_scripts_directory_path (); - - override = g_getenv ("GNOME22_USER_DIR"); - - if (override) { - old_scripts_directory_path = g_build_filename (override, - "nautilus-scripts", - NULL); - } else { - old_scripts_directory_path = g_build_filename (g_get_home_dir (), - ".gnome2", - "nautilus-scripts", - NULL); - } - - if (g_file_test (old_scripts_directory_path, G_FILE_TEST_IS_DIR) - && !g_file_test (scripts_directory_path, G_FILE_TEST_EXISTS)) { - char *updated; - const char *message; - - /* test if we already attempted to migrate first */ - updated = g_build_filename (old_scripts_directory_path, "DEPRECATED-DIRECTORY", NULL); - message = _("Nautilus 3.6 deprecated this directory and tried migrating " - "this configuration to ~/.local/share/nautilus"); - if (!g_file_test (updated, G_FILE_TEST_EXISTS)) { - char *parent_dir; - - parent_dir = g_path_get_dirname (scripts_directory_path); - if (g_mkdir_with_parents (parent_dir, 0700) == 0) { - int fd, res; - - /* rename() works fine if the destination directory is - * empty. - */ - res = g_rename (old_scripts_directory_path, scripts_directory_path); - if (res == -1) { - fd = g_creat (updated, 0600); - if (fd != -1) { - res = write (fd, message, strlen (message)); - close (fd); - } - } - } - g_free (parent_dir); - } - - g_free (updated); - } - - if (g_mkdir_with_parents (scripts_directory_path, 0700) == 0) { - scripts_directory_uri = g_filename_to_uri (scripts_directory_path, NULL, NULL); - scripts_directory_uri_length = strlen (scripts_directory_uri); - } - - g_free (scripts_directory_path); - g_free (old_scripts_directory_path); - - return (scripts_directory_uri != NULL) ? TRUE : FALSE; -} - -static void -scripts_added_or_changed_callback (NautilusDirectory *directory, - GList *files, - gpointer callback_data) -{ - NautilusView *view; - - view = NAUTILUS_VIEW (callback_data); - - if (view->details->active) { - schedule_update_context_menus (view); - } -} - -static void -templates_added_or_changed_callback (NautilusDirectory *directory, - GList *files, - gpointer callback_data) -{ - NautilusView *view; - - view = NAUTILUS_VIEW (callback_data); - - if (view->details->active) { - schedule_update_context_menus (view); - } -} - -static void -add_directory_to_directory_list (NautilusView *view, - NautilusDirectory *directory, - GList **directory_list, - GCallback changed_callback) -{ - NautilusFileAttributes attributes; - - if (g_list_find (*directory_list, directory) == NULL) { - nautilus_directory_ref (directory); - - attributes = - NAUTILUS_FILE_ATTRIBUTES_FOR_ICON | - NAUTILUS_FILE_ATTRIBUTE_INFO | - NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT; - - nautilus_directory_file_monitor_add (directory, directory_list, - FALSE, attributes, - (NautilusDirectoryCallback)changed_callback, view); - - g_signal_connect_object (directory, "files-added", - G_CALLBACK (changed_callback), view, 0); - g_signal_connect_object (directory, "files-changed", - G_CALLBACK (changed_callback), view, 0); - - *directory_list = g_list_append (*directory_list, directory); - } -} - -static void -remove_directory_from_directory_list (NautilusView *view, - NautilusDirectory *directory, - GList **directory_list, - GCallback changed_callback) -{ - *directory_list = g_list_remove (*directory_list, directory); - - g_signal_handlers_disconnect_by_func (directory, - G_CALLBACK (changed_callback), - view); - - nautilus_directory_file_monitor_remove (directory, directory_list); - - nautilus_directory_unref (directory); -} - - -static void -add_directory_to_scripts_directory_list (NautilusView *view, - NautilusDirectory *directory) -{ - add_directory_to_directory_list (view, directory, - &view->details->scripts_directory_list, - G_CALLBACK (scripts_added_or_changed_callback)); -} - -static void -remove_directory_from_scripts_directory_list (NautilusView *view, - NautilusDirectory *directory) -{ - remove_directory_from_directory_list (view, directory, - &view->details->scripts_directory_list, - G_CALLBACK (scripts_added_or_changed_callback)); -} - -static void -add_directory_to_templates_directory_list (NautilusView *view, - NautilusDirectory *directory) -{ - add_directory_to_directory_list (view, directory, - &view->details->templates_directory_list, - G_CALLBACK (templates_added_or_changed_callback)); -} - -static void -remove_directory_from_templates_directory_list (NautilusView *view, - NautilusDirectory *directory) -{ - remove_directory_from_directory_list (view, directory, - &view->details->templates_directory_list, - G_CALLBACK (templates_added_or_changed_callback)); -} - -static void -slot_active (NautilusWindowSlot *slot, - NautilusView *view) -{ - if (view->details->active) { - return; - } - - view->details->active = TRUE; - - /* 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); - - gtk_widget_insert_action_group (GTK_WIDGET (nautilus_view_get_window (view)), - "view", - G_ACTION_GROUP (view->details->view_action_group)); -} - -static void -slot_inactive (NautilusWindowSlot *slot, - NautilusView *view) -{ - if (!view->details->active) { - return; - } - - view->details->active = FALSE; - - remove_update_context_menus_timeout_callback (view); - gtk_widget_insert_action_group (GTK_WIDGET (nautilus_view_get_window (view)), - "view", - NULL); -} - -static void -nautilus_view_grab_focus (GtkWidget *widget) -{ - /* focus the child of the scrolled window if it exists */ - NautilusView *view; - GtkWidget *child; - - view = NAUTILUS_VIEW (widget); - child = gtk_bin_get_child (GTK_BIN (view->details->scrolled_window)); - - GTK_WIDGET_CLASS (nautilus_view_parent_class)->grab_focus (widget); - - if (child) { - gtk_widget_grab_focus (GTK_WIDGET (child)); - } -} - -int -nautilus_view_get_selection_count (NautilusView *view) -{ - /* FIXME: This could be faster if we special cased it in subclasses */ - GList *files; - int len; - - files = nautilus_view_get_selection (NAUTILUS_VIEW (view)); - len = g_list_length (files); - nautilus_file_list_free (files); - - return len; -} - -void -nautilus_view_set_selection (NautilusView *nautilus_view, - GList *selection) -{ - NautilusView *view; - - view = NAUTILUS_VIEW (nautilus_view); - - if (!view->details->loading) { - /* If we aren't still loading, set the selection right now, - * and reveal the new selection. - */ - nautilus_view_call_set_selection (view, selection); - nautilus_view_reveal_selection (view); - } else { - /* If we are still loading, set the list of pending URIs instead. - * done_loading() will eventually select the pending URIs and reveal them. - */ - g_list_free_full (view->details->pending_selection, g_object_unref); - view->details->pending_selection = - g_list_copy_deep (selection, (GCopyFunc) g_object_ref, NULL); - } -} - -static char * -get_bulk_rename_tool () -{ - char *bulk_rename_tool; - g_settings_get (nautilus_preferences, NAUTILUS_PREFERENCES_BULK_RENAME_TOOL, "^ay", &bulk_rename_tool); - return g_strstrip (bulk_rename_tool); -} - -static gboolean -have_bulk_rename_tool () -{ - char *bulk_rename_tool; - gboolean have_tool; - - bulk_rename_tool = get_bulk_rename_tool (); - have_tool = ((bulk_rename_tool != NULL) && (*bulk_rename_tool != '\0')); - g_free (bulk_rename_tool); - return have_tool; -} - -static void -nautilus_view_destroy (GtkWidget *object) -{ - NautilusView *view; - GList *node, *next; - - view = NAUTILUS_VIEW (object); - - nautilus_view_stop_loading (view); - - for (node = view->details->scripts_directory_list; node != NULL; node = next) { - next = node->next; - remove_directory_from_scripts_directory_list (view, node->data); - } - - for (node = view->details->templates_directory_list; node != NULL; node = next) { - next = node->next; - remove_directory_from_templates_directory_list (view, node->data); - } - - while (view->details->subdirectory_list != NULL) { - nautilus_view_remove_subdirectory (view, - view->details->subdirectory_list->data); - } - - remove_update_context_menus_timeout_callback (view); - remove_update_status_idle_callback (view); - - if (view->details->display_selection_idle_id != 0) { - g_source_remove (view->details->display_selection_idle_id); - view->details->display_selection_idle_id = 0; - } - - if (view->details->reveal_selection_idle_id != 0) { - g_source_remove (view->details->reveal_selection_idle_id); - view->details->reveal_selection_idle_id = 0; - } - - if (view->details->floating_bar_set_status_timeout_id != 0) { - g_source_remove (view->details->floating_bar_set_status_timeout_id); - view->details->floating_bar_set_status_timeout_id = 0; - } - - if (view->details->floating_bar_loading_timeout_id != 0) { - g_source_remove (view->details->floating_bar_loading_timeout_id); - view->details->floating_bar_loading_timeout_id = 0; - } - - - if (view->details->directory_as_file) { - nautilus_file_unref (view->details->directory_as_file); - view->details->directory_as_file = NULL; - } - - /* We don't own the slot, so no unref */ - view->details->slot = NULL; - - GTK_WIDGET_CLASS (nautilus_view_parent_class)->destroy (object); -} - -static void -nautilus_view_finalize (GObject *object) -{ - NautilusView *view; - - view = NAUTILUS_VIEW (object); - - g_signal_handlers_disconnect_by_func (nautilus_preferences, - 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, - sort_directories_first_changed_callback, view); - g_signal_handlers_disconnect_by_func (gtk_filechooser_preferences, - show_hidden_files_changed_callback, view); - g_signal_handlers_disconnect_by_func (nautilus_window_state, - nautilus_view_display_selection_info, view); - - g_signal_handlers_disconnect_by_func (gnome_lockdown_preferences, - schedule_update_context_menus, view); - - g_hash_table_destroy (view->details->non_ready_files); - - if (view->details->rename_file_popover != NULL) { - gtk_popover_set_relative_to (GTK_POPOVER (view->details->rename_file_popover), - NULL); - } - - G_OBJECT_CLASS (nautilus_view_parent_class)->finalize (object); -} - -/** - * nautilus_view_display_selection_info: - * - * Display information about the current selection, and notify the view frame of the changed selection. - * @view: NautilusView for which to display selection info. - * - **/ -void -nautilus_view_display_selection_info (NautilusView *view) -{ - GList *selection; - goffset non_folder_size; - gboolean non_folder_size_known; - guint non_folder_count, folder_count, folder_item_count; - gboolean folder_item_count_known; - guint file_item_count; - GList *p; - char *first_item_name; - char *non_folder_count_str; - char *non_folder_item_count_str; - char *folder_count_str; - char *folder_item_count_str; - char *primary_status; - char *detail_status; - NautilusFile *file; - - g_return_if_fail (NAUTILUS_IS_VIEW (view)); - - selection = nautilus_view_get_selection (view); - - folder_item_count_known = TRUE; - folder_count = 0; - folder_item_count = 0; - non_folder_count = 0; - non_folder_size_known = FALSE; - non_folder_size = 0; - first_item_name = NULL; - folder_count_str = NULL; - folder_item_count_str = NULL; - non_folder_count_str = NULL; - non_folder_item_count_str = NULL; - - for (p = selection; p != NULL; p = p->next) { - file = p->data; - if (nautilus_file_is_directory (file)) { - folder_count++; - if (nautilus_file_get_directory_item_count (file, &file_item_count, NULL)) { - folder_item_count += file_item_count; - } else { - folder_item_count_known = FALSE; - } - } else { - non_folder_count++; - if (!nautilus_file_can_get_size (file)) { - non_folder_size_known = TRUE; - non_folder_size += nautilus_file_get_size (file); - } - } - - if (first_item_name == NULL) { - first_item_name = nautilus_file_get_display_name (file); - } - } - - nautilus_file_list_free (selection); - - /* Break out cases for localization's sake. But note that there are still pieces - * being assembled in a particular order, which may be a problem for some localizers. - */ - - if (folder_count != 0) { - if (folder_count == 1 && non_folder_count == 0) { - folder_count_str = g_strdup_printf (_("“%s” selected"), first_item_name); - } else { - folder_count_str = g_strdup_printf (ngettext("%'d folder selected", - "%'d folders selected", - folder_count), - folder_count); - } - - if (folder_count == 1) { - if (!folder_item_count_known) { - folder_item_count_str = g_strdup (""); - } else { - folder_item_count_str = g_strdup_printf (ngettext("(containing %'d item)", - "(containing %'d items)", - folder_item_count), - folder_item_count); - } - } - else { - if (!folder_item_count_known) { - folder_item_count_str = g_strdup (""); - } else { - /* translators: this is preceded with a string of form 'N folders' (N more than 1) */ - folder_item_count_str = g_strdup_printf (ngettext("(containing a total of %'d item)", - "(containing a total of %'d items)", - folder_item_count), - folder_item_count); - } - - } - } - - if (non_folder_count != 0) { - if (folder_count == 0) { - if (non_folder_count == 1) { - non_folder_count_str = g_strdup_printf (_("“%s” selected"), - first_item_name); - } else { - non_folder_count_str = g_strdup_printf (ngettext("%'d item selected", - "%'d items selected", - non_folder_count), - non_folder_count); - } - } else { - /* Folders selected also, use "other" terminology */ - non_folder_count_str = g_strdup_printf (ngettext("%'d other item selected", - "%'d other items selected", - non_folder_count), - non_folder_count); - } - - if (non_folder_size_known) { - char *size_string; - - size_string = g_format_size (non_folder_size); - /* This is marked for translation in case a localiser - * needs to use something other than parentheses. The - * the message in parentheses is the size of the selected items. - */ - non_folder_item_count_str = g_strdup_printf (_("(%s)"), size_string); - g_free (size_string); - } else { - non_folder_item_count_str = g_strdup (""); - } - } - - if (folder_count == 0 && non_folder_count == 0) { - primary_status = NULL; - detail_status = NULL; - } else if (folder_count == 0) { - primary_status = g_strdup (non_folder_count_str); - detail_status = g_strdup (non_folder_item_count_str); - } else if (non_folder_count == 0) { - primary_status = g_strdup (folder_count_str); - detail_status = g_strdup (folder_item_count_str); - } else { - /* This is marked for translation in case a localizer - * needs to change ", " to something else. The comma - * is between the message about the number of folders - * and the number of items in those folders and the - * message about the number of other items and the - * total size of those items. - */ - primary_status = g_strdup_printf (_("%s %s, %s %s"), - folder_count_str, - folder_item_count_str, - non_folder_count_str, - non_folder_item_count_str); - detail_status = NULL; - } - - g_free (first_item_name); - g_free (folder_count_str); - g_free (folder_item_count_str); - g_free (non_folder_count_str); - g_free (non_folder_item_count_str); - - set_floating_bar_status (view, primary_status, detail_status); - - g_free (primary_status); - g_free (detail_status); -} - -static void -nautilus_view_send_selection_change (NautilusView *view) -{ - g_signal_emit (view, signals[SELECTION_CHANGED], 0); -} - -void -nautilus_view_load_location (NautilusView *nautilus_view, - GFile *location) -{ - NautilusDirectory *directory; - - nautilus_profile_start (NULL); - directory = nautilus_directory_get (location); - load_directory (nautilus_view, directory); - nautilus_directory_unref (directory); - nautilus_profile_end (NULL); -} - -static gboolean -reveal_selection_idle_callback (gpointer data) -{ - NautilusView *view; - - view = NAUTILUS_VIEW (data); - - view->details->reveal_selection_idle_id = 0; - nautilus_view_reveal_selection (view); - - return FALSE; -} - -static void -done_loading (NautilusView *view, - gboolean all_files_seen) -{ - GList *selection; - gboolean do_reveal = FALSE; - - if (!view->details->loading) { - return; - } - - nautilus_profile_start (NULL); - - /* This can be called during destruction, in which case we set the model - * as NULL. */ - if (view->details->model != NULL) { - nautilus_view_update_toolbar_menus (view); - remove_loading_floating_bar (view); - schedule_update_context_menus (view); - schedule_update_status (view); - reset_update_interval (view); - - selection = view->details->pending_selection; - - if (nautilus_view_is_search (view) && all_files_seen) { - nautilus_view_select_first (view); - do_reveal = TRUE; - } else if (selection != NULL && all_files_seen) { - view->details->pending_selection = NULL; - - nautilus_view_call_set_selection (view, selection); - g_list_free_full (selection, g_object_unref); - do_reveal = TRUE; - } - - if (do_reveal) { - if (NAUTILUS_IS_LIST_VIEW (view)) { - /* HACK: We should be able to directly call reveal_selection here, - * but at this point the GtkTreeView hasn't allocated the new nodes - * yet, and it has a bug in the scroll calculation dealing with this - * special case. It would always make the selection the top row, even - * if no scrolling would be neccessary to reveal it. So we let it - * allocate before revealing. - */ - if (view->details->reveal_selection_idle_id != 0) { - g_source_remove (view->details->reveal_selection_idle_id); - } - view->details->reveal_selection_idle_id = - g_idle_add (reveal_selection_idle_callback, view); - } else { - nautilus_view_reveal_selection (view); - } - } - nautilus_view_display_selection_info (view); - } - - view->details->loading = FALSE; - g_signal_emit (view, signals[END_LOADING], 0, all_files_seen); - - check_empty_states (view); - - nautilus_profile_end (NULL); -} - - -typedef struct { - GHashTable *debuting_files; - GList *added_files; -} DebutingFilesData; - -static void -debuting_files_data_free (DebutingFilesData *data) -{ - g_hash_table_unref (data->debuting_files); - nautilus_file_list_free (data->added_files); - g_free (data); -} - -/* This signal handler watch for the arrival of the icons created - * as the result of a file operation. Once the last one is detected - * it selects and reveals them all. - */ -static void -debuting_files_add_file_callback (NautilusView *view, - NautilusFile *new_file, - NautilusDirectory *directory, - DebutingFilesData *data) -{ - GFile *location; - - nautilus_profile_start (NULL); - - location = nautilus_file_get_location (new_file); - - if (g_hash_table_remove (data->debuting_files, location)) { - nautilus_file_ref (new_file); - data->added_files = g_list_prepend (data->added_files, new_file); - - if (g_hash_table_size (data->debuting_files) == 0) { - nautilus_view_call_set_selection (view, data->added_files); - nautilus_view_reveal_selection (view); - g_signal_handlers_disconnect_by_func (view, - G_CALLBACK (debuting_files_add_file_callback), - data); - } - } - - nautilus_profile_end (NULL); - - g_object_unref (location); -} - -typedef struct { - GList *added_files; - NautilusView *directory_view; -} CopyMoveDoneData; - -static void -copy_move_done_data_free (CopyMoveDoneData *data) -{ - g_assert (data != NULL); - - if (data->directory_view != NULL) { - g_object_remove_weak_pointer (G_OBJECT (data->directory_view), - (gpointer *) &data->directory_view); - } - - nautilus_file_list_free (data->added_files); - g_free (data); -} - -static void -pre_copy_move_add_file_callback (NautilusView *view, - NautilusFile *new_file, - NautilusDirectory *directory, - CopyMoveDoneData *data) -{ - nautilus_file_ref (new_file); - data->added_files = g_list_prepend (data->added_files, new_file); -} - -/* This needs to be called prior to nautilus_file_operations_copy_move. - * It hooks up a signal handler to catch any icons that get added before - * the copy_done_callback is invoked. The return value should be passed - * as the data for uri_copy_move_done_callback. - */ -static CopyMoveDoneData * -pre_copy_move (NautilusView *directory_view) -{ - CopyMoveDoneData *copy_move_done_data; - - copy_move_done_data = g_new0 (CopyMoveDoneData, 1); - copy_move_done_data->directory_view = directory_view; - - g_object_add_weak_pointer (G_OBJECT (copy_move_done_data->directory_view), - (gpointer *) ©_move_done_data->directory_view); - - /* We need to run after the default handler adds the folder we want to - * operate on. The ADD_FILE signal is registered as G_SIGNAL_RUN_LAST, so we - * must use connect_after. - */ - g_signal_connect (directory_view, "add-file", - G_CALLBACK (pre_copy_move_add_file_callback), copy_move_done_data); - - return copy_move_done_data; -} - -/* This function is used to pull out any debuting uris that were added - * and (as a side effect) remove them from the debuting uri hash table. - */ -static gboolean -copy_move_done_partition_func (gpointer data, gpointer callback_data) -{ - GFile *location; - gboolean result; - - location = nautilus_file_get_location (NAUTILUS_FILE (data)); - result = g_hash_table_remove ((GHashTable *) callback_data, location); - g_object_unref (location); - - return result; -} - -static gboolean -remove_not_really_moved_files (gpointer key, - gpointer value, - gpointer callback_data) -{ - GList **added_files; - GFile *loc; - - loc = key; - - if (GPOINTER_TO_INT (value)) { - return FALSE; - } - - added_files = callback_data; - *added_files = g_list_prepend (*added_files, - nautilus_file_get (loc)); - return TRUE; -} - -/* When this function is invoked, the file operation is over, but all - * the icons may not have been added to the directory view yet, so - * we can't select them yet. - * - * We're passed a hash table of the uri's to look out for, we hook - * up a signal handler to await their arrival. - */ -static void -copy_move_done_callback (GHashTable *debuting_files, - gboolean success, - gpointer data) -{ - NautilusView *directory_view; - CopyMoveDoneData *copy_move_done_data; - DebutingFilesData *debuting_files_data; - - copy_move_done_data = (CopyMoveDoneData *) data; - directory_view = copy_move_done_data->directory_view; - - if (directory_view != NULL) { - g_assert (NAUTILUS_IS_VIEW (directory_view)); - - debuting_files_data = g_new (DebutingFilesData, 1); - debuting_files_data->debuting_files = g_hash_table_ref (debuting_files); - debuting_files_data->added_files = eel_g_list_partition - (copy_move_done_data->added_files, - copy_move_done_partition_func, - debuting_files, - ©_move_done_data->added_files); - - /* We're passed the same data used by pre_copy_move_add_file_callback, so disconnecting - * it will free data. We've already siphoned off the added_files we need, and stashed the - * directory_view pointer. - */ - g_signal_handlers_disconnect_by_func (directory_view, - G_CALLBACK (pre_copy_move_add_file_callback), - data); - - /* Any items in the debuting_files hash table that have - * "FALSE" as their value aren't really being copied - * or moved, so we can't wait for an add_file signal - * to come in for those. - */ - g_hash_table_foreach_remove (debuting_files, - remove_not_really_moved_files, - &debuting_files_data->added_files); - - if (g_hash_table_size (debuting_files) == 0) { - /* on the off-chance that all the icons have already been added */ - if (debuting_files_data->added_files != NULL) { - nautilus_view_call_set_selection (directory_view, - debuting_files_data->added_files); - nautilus_view_reveal_selection (directory_view); - } - debuting_files_data_free (debuting_files_data); - } else { - /* We need to run after the default handler adds the folder we want to - * operate on. The ADD_FILE signal is registered as G_SIGNAL_RUN_LAST, so we - * must use connect_after. - */ - g_signal_connect_data (directory_view, - "add-file", - G_CALLBACK (debuting_files_add_file_callback), - debuting_files_data, - (GClosureNotify) debuting_files_data_free, - G_CONNECT_AFTER); - } - /* Schedule menu update for undo items */ - schedule_update_context_menus (directory_view); - } - - copy_move_done_data_free (copy_move_done_data); -} - -static gboolean -view_file_still_belongs (NautilusView *view, - NautilusFile *file, - NautilusDirectory *directory) -{ - if (view->details->model != directory && - g_list_find (view->details->subdirectory_list, directory) == NULL) { - return FALSE; - } - - return nautilus_directory_contains_file (directory, file); -} - -static gboolean -still_should_show_file (NautilusView *view, NautilusFile *file, NautilusDirectory *directory) -{ - return nautilus_view_should_show_file (view, file) && - view_file_still_belongs (view, file, directory); -} - -static gboolean -ready_to_load (NautilusFile *file) -{ - return nautilus_file_check_if_ready (file, - NAUTILUS_FILE_ATTRIBUTES_FOR_ICON); -} - -static int -compare_files_cover (gconstpointer a, gconstpointer b, gpointer callback_data) -{ - const FileAndDirectory *fad1, *fad2; - NautilusView *view; - - view = callback_data; - fad1 = a; fad2 = b; - - if (fad1->directory < fad2->directory) { - return -1; - } else if (fad1->directory > fad2->directory) { - return 1; - } else { - return NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->compare_files (view, fad1->file, fad2->file); - } -} -static void -sort_files (NautilusView *view, GList **list) -{ - *list = g_list_sort_with_data (*list, compare_files_cover, view); - -} - -/* Go through all the new added and changed files. - * Put any that are not ready to load in the non_ready_files hash table. - * Add all the rest to the old_added_files and old_changed_files lists. - * Sort the old_*_files lists if anything was added to them. - */ -static void -process_new_files (NautilusView *view) -{ - GList *new_added_files, *new_changed_files, *old_added_files, *old_changed_files; - GHashTable *non_ready_files; - GList *node, *next; - FileAndDirectory *pending; - gboolean in_non_ready; - - new_added_files = view->details->new_added_files; - view->details->new_added_files = NULL; - new_changed_files = view->details->new_changed_files; - view->details->new_changed_files = NULL; - - non_ready_files = view->details->non_ready_files; - - old_added_files = view->details->old_added_files; - old_changed_files = view->details->old_changed_files; - - /* Newly added files go into the old_added_files list if they're - * ready, and into the hash table if they're not. - */ - for (node = new_added_files; node != NULL; node = next) { - next = node->next; - pending = (FileAndDirectory *)node->data; - in_non_ready = g_hash_table_lookup (non_ready_files, pending) != NULL; - if (nautilus_view_should_show_file (view, pending->file)) { - if (ready_to_load (pending->file)) { - if (in_non_ready) { - g_hash_table_remove (non_ready_files, pending); - } - new_added_files = g_list_delete_link (new_added_files, node); - old_added_files = g_list_prepend (old_added_files, pending); - } else { - if (!in_non_ready) { - new_added_files = g_list_delete_link (new_added_files, node); - g_hash_table_insert (non_ready_files, pending, pending); - } - } - } - } - file_and_directory_list_free (new_added_files); - - /* Newly changed files go into the old_added_files list if they're ready - * and were seen non-ready in the past, into the old_changed_files list - * if they are read and were not seen non-ready in the past, and into - * the hash table if they're not ready. - */ - for (node = new_changed_files; node != NULL; node = next) { - next = node->next; - pending = (FileAndDirectory *)node->data; - if (!still_should_show_file (view, pending->file, pending->directory) || ready_to_load (pending->file)) { - if (g_hash_table_lookup (non_ready_files, pending) != NULL) { - g_hash_table_remove (non_ready_files, pending); - if (still_should_show_file (view, pending->file, pending->directory)) { - new_changed_files = g_list_delete_link (new_changed_files, node); - old_added_files = g_list_prepend (old_added_files, pending); - } - } else if (nautilus_view_should_show_file (view, pending->file)) { - new_changed_files = g_list_delete_link (new_changed_files, node); - old_changed_files = g_list_prepend (old_changed_files, pending); - } - } - } - file_and_directory_list_free (new_changed_files); - - /* If any files were added to old_added_files, then resort it. */ - if (old_added_files != view->details->old_added_files) { - view->details->old_added_files = old_added_files; - sort_files (view, &view->details->old_added_files); - } - - /* Resort old_changed_files too, since file attributes - * relevant to sorting could have changed. - */ - if (old_changed_files != view->details->old_changed_files) { - view->details->old_changed_files = old_changed_files; - sort_files (view, &view->details->old_changed_files); - } - -} - -static void -process_old_files (NautilusView *view) -{ - GList *files_added, *files_changed, *node; - FileAndDirectory *pending; - GList *selection, *files; - gboolean send_selection_change; - - files_added = view->details->old_added_files; - files_changed = view->details->old_changed_files; - - send_selection_change = FALSE; - - if (files_added != NULL || files_changed != NULL) { - g_signal_emit (view, signals[BEGIN_FILE_CHANGES], 0); - - for (node = files_added; node != NULL; node = node->next) { - pending = node->data; - g_signal_emit (view, - signals[ADD_FILE], 0, pending->file, pending->directory); - } - - for (node = files_changed; node != NULL; node = node->next) { - pending = node->data; - g_signal_emit (view, - signals[still_should_show_file (view, pending->file, pending->directory) - ? FILE_CHANGED : REMOVE_FILE], 0, - pending->file, pending->directory); - } - - g_signal_emit (view, signals[END_FILE_CHANGES], 0); - check_empty_states (view); - - if (files_changed != NULL) { - selection = nautilus_view_get_selection (view); - files = file_and_directory_list_to_files (files_changed); - send_selection_change = eel_g_lists_sort_and_check_for_intersection - (&files, &selection); - nautilus_file_list_free (files); - nautilus_file_list_free (selection); - } - - file_and_directory_list_free (view->details->old_added_files); - view->details->old_added_files = NULL; - - file_and_directory_list_free (view->details->old_changed_files); - view->details->old_changed_files = NULL; - } - - if (send_selection_change) { - /* Send a selection change since some file names could - * have changed. - */ - nautilus_view_send_selection_change (view); - } -} - -static void -display_pending_files (NautilusView *view) -{ - process_new_files (view); - process_old_files (view); - - if (view->details->model != NULL - && nautilus_directory_are_all_files_seen (view->details->model) - && g_hash_table_size (view->details->non_ready_files) == 0) { - done_loading (view, TRUE); - } -} - -static gboolean -display_selection_info_idle_callback (gpointer data) -{ - NautilusView *view; - - view = NAUTILUS_VIEW (data); - - g_object_ref (G_OBJECT (view)); - - view->details->display_selection_idle_id = 0; - nautilus_view_display_selection_info (view); - nautilus_view_send_selection_change (view); - - g_object_unref (G_OBJECT (view)); - - return FALSE; -} - -static void -remove_update_context_menus_timeout_callback (NautilusView *view) -{ - 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_context_menus_if_pending (NautilusView *view) -{ - remove_update_context_menus_timeout_callback (view); - - nautilus_view_update_context_menus(view); -} - -static gboolean -update_context_menus_timeout_callback (gpointer data) -{ - NautilusView *view; - - view = NAUTILUS_VIEW (data); - - g_object_ref (G_OBJECT (view)); - - view->details->update_context_menus_timeout_id = 0; - nautilus_view_update_context_menus(view); - - g_object_unref (G_OBJECT (view)); - - return FALSE; -} - -static gboolean -display_pending_callback (gpointer data) -{ - NautilusView *view; - - view = NAUTILUS_VIEW (data); - - g_object_ref (G_OBJECT (view)); - - view->details->display_pending_source_id = 0; - - display_pending_files (view); - - g_object_unref (G_OBJECT (view)); - - return FALSE; -} - -static void -schedule_idle_display_of_pending_files (NautilusView *view) -{ - /* Get rid of a pending source as it might be a timeout */ - unschedule_display_of_pending_files (view); - - /* We want higher priority than the idle that handles the relayout - to avoid a resort on each add. But we still want to allow repaints - and other hight prio events while we have pending files to show. */ - view->details->display_pending_source_id = - g_idle_add_full (G_PRIORITY_DEFAULT_IDLE - 20, - display_pending_callback, view, NULL); -} - -static void -schedule_timeout_display_of_pending_files (NautilusView *view, guint interval) -{ - /* No need to schedule an update if there's already one pending. */ - if (view->details->display_pending_source_id != 0) { - return; - } - - view->details->display_pending_source_id = - g_timeout_add (interval, display_pending_callback, view); -} - -static void -unschedule_display_of_pending_files (NautilusView *view) -{ - /* Get rid of source if it's active. */ - if (view->details->display_pending_source_id != 0) { - g_source_remove (view->details->display_pending_source_id); - view->details->display_pending_source_id = 0; - } -} - -static void -queue_pending_files (NautilusView *view, - NautilusDirectory *directory, - GList *files, - GList **pending_list) -{ - if (files == NULL) { - return; - } - - *pending_list = g_list_concat (file_and_directory_list_from_files (directory, files), - *pending_list); - - if (! view->details->loading || nautilus_directory_are_all_files_seen (directory)) { - schedule_timeout_display_of_pending_files (view, view->details->update_interval); - } -} - -static void -remove_changes_timeout_callback (NautilusView *view) -{ - if (view->details->changes_timeout_id != 0) { - g_source_remove (view->details->changes_timeout_id); - view->details->changes_timeout_id = 0; - } -} - -static void -reset_update_interval (NautilusView *view) -{ - view->details->update_interval = UPDATE_INTERVAL_MIN; - remove_changes_timeout_callback (view); - /* Reschedule a pending timeout to idle */ - if (view->details->display_pending_source_id != 0) { - schedule_idle_display_of_pending_files (view); - } -} - -static gboolean -changes_timeout_callback (gpointer data) -{ - gint64 now; - gint64 time_delta; - gboolean ret; - NautilusView *view; - - view = NAUTILUS_VIEW (data); - - g_object_ref (G_OBJECT (view)); - - now = g_get_monotonic_time (); - time_delta = now - view->details->last_queued; - - if (time_delta < UPDATE_INTERVAL_RESET*1000) { - if (view->details->update_interval < UPDATE_INTERVAL_MAX && - view->details->loading) { - /* Increase */ - view->details->update_interval += UPDATE_INTERVAL_INC; - } - ret = TRUE; - } else { - /* Reset */ - reset_update_interval (view); - ret = FALSE; - } - - g_object_unref (G_OBJECT (view)); - - return ret; -} - -static void -schedule_changes (NautilusView *view) -{ - /* Remember when the change was queued */ - view->details->last_queued = g_get_monotonic_time (); - - /* No need to schedule if there are already changes pending or during loading */ - if (view->details->changes_timeout_id != 0 || - view->details->loading) { - return; - } - - view->details->changes_timeout_id = - g_timeout_add (UPDATE_INTERVAL_TIMEOUT_INTERVAL, changes_timeout_callback, view); -} - -static void -files_added_callback (NautilusDirectory *directory, - GList *files, - gpointer callback_data) -{ - NautilusView *view; - GtkWindow *window; - char *uri; - - view = NAUTILUS_VIEW (callback_data); - - nautilus_profile_start (NULL); - - window = nautilus_view_get_containing_window (view); - uri = nautilus_view_get_uri (view); - DEBUG_FILES (files, "Files added in window %p: %s", - window, uri ? uri : "(no directory)"); - g_free (uri); - - schedule_changes (view); - - queue_pending_files (view, directory, files, &view->details->new_added_files); - - /* The number of items could have changed */ - schedule_update_status (view); - - nautilus_profile_end (NULL); -} - -static void -files_changed_callback (NautilusDirectory *directory, - GList *files, - gpointer callback_data) -{ - NautilusView *view; - GtkWindow *window; - char *uri; - - view = NAUTILUS_VIEW (callback_data); - - window = nautilus_view_get_containing_window (view); - uri = nautilus_view_get_uri (view); - DEBUG_FILES (files, "Files changed in window %p: %s", - window, uri ? uri : "(no directory)"); - g_free (uri); - - schedule_changes (view); - - queue_pending_files (view, directory, files, &view->details->new_changed_files); - - /* The free space or the number of items could have changed */ - schedule_update_status (view); - - /* 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_context_menus (view); -} - -static void -done_loading_callback (NautilusDirectory *directory, - gpointer callback_data) -{ - NautilusView *view; - - view = NAUTILUS_VIEW (callback_data); - - nautilus_profile_start (NULL); - process_new_files (view); - if (g_hash_table_size (view->details->non_ready_files) == 0) { - /* Unschedule a pending update and schedule a new one with the minimal - * update interval. This gives the view a short chance at gathering the - * (cached) deep counts. - */ - unschedule_display_of_pending_files (view); - schedule_timeout_display_of_pending_files (view, UPDATE_INTERVAL_MIN); - - remove_loading_floating_bar (view); - } - nautilus_profile_end (NULL); -} - -static void -load_error_callback (NautilusDirectory *directory, - GError *error, - gpointer callback_data) -{ - NautilusView *view; - - view = NAUTILUS_VIEW (callback_data); - - /* FIXME: By doing a stop, we discard some pending files. Is - * that OK? - */ - nautilus_view_stop_loading (view); - - nautilus_report_error_loading_directory - (nautilus_view_get_directory_as_file (view), - error, - nautilus_view_get_containing_window (view)); -} - -void -nautilus_view_add_subdirectory (NautilusView *view, - NautilusDirectory*directory) -{ - NautilusFileAttributes attributes; - - g_assert (!g_list_find (view->details->subdirectory_list, directory)); - - nautilus_directory_ref (directory); - - attributes = - NAUTILUS_FILE_ATTRIBUTES_FOR_ICON | - NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT | - NAUTILUS_FILE_ATTRIBUTE_INFO | - NAUTILUS_FILE_ATTRIBUTE_LINK_INFO | - NAUTILUS_FILE_ATTRIBUTE_MOUNT | - NAUTILUS_FILE_ATTRIBUTE_EXTENSION_INFO; - - nautilus_directory_file_monitor_add (directory, - &view->details->model, - view->details->show_hidden_files, - attributes, - files_added_callback, view); - - g_signal_connect - (directory, "files-added", - G_CALLBACK (files_added_callback), view); - g_signal_connect - (directory, "files-changed", - G_CALLBACK (files_changed_callback), view); - - view->details->subdirectory_list = g_list_prepend ( - view->details->subdirectory_list, directory); -} - -void -nautilus_view_remove_subdirectory (NautilusView *view, - NautilusDirectory*directory) -{ - g_assert (g_list_find (view->details->subdirectory_list, directory)); - - view->details->subdirectory_list = g_list_remove ( - view->details->subdirectory_list, directory); - - g_signal_handlers_disconnect_by_func (directory, - G_CALLBACK (files_added_callback), - view); - g_signal_handlers_disconnect_by_func (directory, - G_CALLBACK (files_changed_callback), - view); - - nautilus_directory_file_monitor_remove (directory, &view->details->model); - - nautilus_directory_unref (directory); -} - -/** - * nautilus_view_get_loading: - * @view: an #NautilusView. - * - * Return value: #gboolean inicating whether @view is currently loaded. - * - **/ -gboolean -nautilus_view_get_loading (NautilusView *view) -{ - g_return_val_if_fail (NAUTILUS_IS_VIEW (view), FALSE); - - return view->details->loading; -} - -/** - * nautilus_view_get_model: - * - * Get the model for this NautilusView. - * @view: NautilusView of interest. - * - * Return value: NautilusDirectory for this view. - * - **/ -NautilusDirectory * -nautilus_view_get_model (NautilusView *view) -{ - g_return_val_if_fail (NAUTILUS_IS_VIEW (view), NULL); - - return view->details->model; -} - -GtkWidget* -nautilus_view_get_content_widget (NautilusView *view) -{ - g_return_val_if_fail (NAUTILUS_IS_VIEW (view), NULL); - - return view->details->scrolled_window; -} - -GdkAtom -nautilus_view_get_copied_files_atom (NautilusView *view) -{ - g_return_val_if_fail (NAUTILUS_IS_VIEW (view), GDK_NONE); - - return copied_files_atom; -} - -static void -offset_drop_points (GArray *relative_item_points, - int x_offset, int y_offset) -{ - guint index; - - if (relative_item_points == NULL) { - return; - } - - for (index = 0; index < relative_item_points->len; index++) { - g_array_index (relative_item_points, GdkPoint, index).x += x_offset; - g_array_index (relative_item_points, GdkPoint, index).y += y_offset; - } -} - -/* special_link_in_selection - * - * Return TRUE if one of our special links is in the selection. - * Special links include the following: - * NAUTILUS_DESKTOP_LINK_TRASH, NAUTILUS_DESKTOP_LINK_HOME, NAUTILUS_DESKTOP_LINK_MOUNT - */ - -static gboolean -special_link_in_selection (GList *selection) -{ - gboolean saw_link; - GList *node; - NautilusFile *file; - - saw_link = FALSE; - - for (node = selection; node != NULL; node = node->next) { - file = NAUTILUS_FILE (node->data); - - saw_link = NAUTILUS_IS_DESKTOP_ICON_FILE (file); - - if (saw_link) { - break; - } - } - - return saw_link; -} - -/* desktop_or_home_dir_in_selection - * - * Return TRUE if either the desktop or the home directory is in the selection. - */ - -static gboolean -desktop_or_home_dir_in_selection (GList *selection) -{ - gboolean saw_desktop_or_home_dir; - GList *node; - NautilusFile *file; - - saw_desktop_or_home_dir = FALSE; - - for (node = selection; node != NULL; node = node->next) { - file = NAUTILUS_FILE (node->data); - - saw_desktop_or_home_dir = - nautilus_file_is_home (file) - || nautilus_file_is_desktop_directory (file); - - if (saw_desktop_or_home_dir) { - break; - } - } - - return saw_desktop_or_home_dir; -} - -static void -trash_or_delete_done_cb (GHashTable *debuting_uris, - gboolean user_cancel, - NautilusView *view) -{ - if (user_cancel) { - view->details->selection_was_removed = FALSE; - } -} - -static void -trash_or_delete_files (GtkWindow *parent_window, - const GList *files, - NautilusView *view) -{ - GList *locations; - const GList *node; - - locations = NULL; - for (node = files; node != NULL; node = node->next) { - locations = g_list_prepend (locations, - nautilus_file_get_location ((NautilusFile *) node->data)); - } - - locations = g_list_reverse (locations); - - nautilus_file_operations_trash_or_delete (locations, - parent_window, - (NautilusDeleteCallback) trash_or_delete_done_cb, - view); - g_list_free_full (locations, g_object_unref); -} - -static gboolean -can_rename_file (NautilusView *view, NautilusFile *file) -{ - return nautilus_file_can_rename (file); -} - -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) -{ - g_return_if_fail (NAUTILUS_IS_VIEW (view)); - - if (event != NULL) { - view->details->context_menu_position.x = event->x; - view->details->context_menu_position.y = event->y; - } else { - view->details->context_menu_position.x = -1; - view->details->context_menu_position.y = -1; - } -} - -NautilusFile * -nautilus_view_get_directory_as_file (NautilusView *view) -{ - g_assert (NAUTILUS_IS_VIEW (view)); - - return view->details->directory_as_file; -} - -static GdkPixbuf * -get_menu_icon_for_file (NautilusFile *file, - GtkWidget *widget) -{ - NautilusIconInfo *info; - GdkPixbuf *pixbuf; - int size, scale; - - size = nautilus_get_icon_size_for_stock_size (GTK_ICON_SIZE_MENU); - scale = gtk_widget_get_scale_factor (widget); - - info = nautilus_file_get_icon (file, size, scale, 0); - pixbuf = nautilus_icon_info_get_pixbuf_nodefault_at_size (info, size); - g_object_unref (info); - - return pixbuf; -} - -static GList * -get_extension_selection_menu_items (NautilusView *view) -{ - NautilusWindow *window; - GList *items; - GList *providers; - GList *l; - GList *selection; - - window = nautilus_view_get_window (view); - selection = nautilus_view_get_selection (view); - 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, - GTK_WIDGET (window), - selection); - items = g_list_concat (items, file_items); - } - - nautilus_module_extension_list_free (providers); - - return items; -} - -static GList * -get_extension_background_menu_items (NautilusView *view) -{ - NautilusWindow *window; - NautilusFile *file; - GList *items; - GList *providers; - GList *l; - - window = nautilus_view_get_window (view); - providers = nautilus_module_get_extensions_for_type (NAUTILUS_TYPE_MENU_PROVIDER); - file = nautilus_window_slot_get_file (view->details->slot); - 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_background_items (provider, - GTK_WIDGET (window), - file); - items = g_list_concat (items, file_items); - } - - nautilus_module_extension_list_free (providers); - - return items; -} - -static void -extension_action_callback (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - NautilusMenuItem *item = user_data; - nautilus_menu_item_activate (item); -} - -static void -add_extension_action (NautilusView *view, - NautilusMenuItem *item, - const char *action_name) -{ - gboolean sensitive; - GSimpleAction *action; - - g_object_get (item, - "sensitive", &sensitive, - NULL); - - action = g_simple_action_new (action_name, NULL); - g_signal_connect_data (action, "activate", - G_CALLBACK (extension_action_callback), - g_object_ref (item), - (GClosureNotify) g_object_unref, 0); - - g_action_map_add_action (G_ACTION_MAP (view->details->view_action_group), - G_ACTION (action)); - g_simple_action_set_enabled (action, sensitive); - - g_object_unref (action); -} - -static GMenu * -build_menu_for_extension_menu_items (NautilusView *view, - const gchar *extension_prefix, - GList *menu_items) -{ - GList *l; - GMenu *gmenu; - gint idx = 0; - - gmenu = g_menu_new (); - - for (l = menu_items; l; l = l->next) { - NautilusMenuItem *item; - NautilusMenu *menu; - GMenuItem *menu_item; - char *name, *label; - char *extension_id, *prefix, *parsed_name, *detailed_action_name; - - item = NAUTILUS_MENU_ITEM (l->data); - - g_object_get (item, - "label", &label, - "menu", &menu, - "name", &name, - NULL); - - extension_id = g_strdup_printf ("%s_%d", extension_prefix, idx); - prefix = g_strdup_printf ("extension_%s_", extension_id); - parsed_name = nautilus_escape_action_name (name, prefix); - add_extension_action (view, item, parsed_name); - - detailed_action_name = g_strconcat ("view.", parsed_name, NULL); - menu_item = g_menu_item_new (label, detailed_action_name); - - if (menu != NULL) { - GList *children; - GMenu *children_menu; - - children = nautilus_menu_get_items (menu); - children_menu = build_menu_for_extension_menu_items (view, extension_id, children); - g_menu_item_set_submenu (menu_item, G_MENU_MODEL (children_menu)); - - nautilus_menu_item_list_free (children); - g_object_unref (children_menu); - } - - g_menu_append_item (gmenu, menu_item); - idx++; - - g_free (extension_id); - g_free (parsed_name); - g_free (prefix); - g_free (detailed_action_name); - g_free (name); - g_free (label); - g_object_unref (menu_item); - } - - return gmenu; -} - -static void -add_extension_menu_items (NautilusView *view, - const gchar *extension_prefix, - GList *menu_items, - GMenu *insertion_menu) -{ - GMenu *menu; - - menu = build_menu_for_extension_menu_items (view, extension_prefix, menu_items); - nautilus_gmenu_merge (insertion_menu, - menu, - "extensions", - FALSE); - - g_object_unref (menu); -} - -static void -update_extensions_menus (NautilusView *view) -{ - GList *selection_items, *background_items; - - selection_items = get_extension_selection_menu_items (view); - if (selection_items != NULL) { - add_extension_menu_items (view, - "selection", - selection_items, - view->details->selection_menu); - nautilus_menu_item_list_free (selection_items); - } - - background_items = get_extension_background_menu_items (view); - if (background_items != NULL) { - add_extension_menu_items (view, - "background", - background_items, - view->details->background_menu); - nautilus_menu_item_list_free (background_items); - } -} - -static char * -change_to_view_directory (NautilusView *view) -{ - char *path; - char *old_path; - - old_path = g_get_current_dir (); - - path = get_view_directory (view); - - /* FIXME: What to do about non-local directories? */ - if (path != NULL) { - g_chdir (path); - } - - g_free (path); - - return old_path; -} - -static char ** -get_file_names_as_parameter_array (GList *selection, - NautilusDirectory *model) -{ - NautilusFile *file; - char **parameters; - GList *node; - GFile *file_location; - GFile *model_location; - int i; - - if (model == NULL) { - return NULL; - } - - parameters = g_new (char *, g_list_length (selection) + 1); - - model_location = nautilus_directory_get_location (model); - - for (node = selection, i = 0; node != NULL; node = node->next, i++) { - file = NAUTILUS_FILE (node->data); - - if (!nautilus_file_is_local (file)) { - parameters[i] = NULL; - g_strfreev (parameters); - return NULL; - } - - file_location = nautilus_file_get_location (NAUTILUS_FILE (node->data)); - parameters[i] = g_file_get_relative_path (model_location, file_location); - if (parameters[i] == NULL) { - parameters[i] = g_file_get_path (file_location); - } - g_object_unref (file_location); - } - - g_object_unref (model_location); - - parameters[i] = NULL; - return parameters; -} - -static char * -get_file_paths_or_uris_as_newline_delimited_string (GList *selection, gboolean get_paths) -{ - char *path; - char *uri; - char *result; - NautilusDesktopLink *link; - GString *expanding_string; - GList *node; - GFile *location; - - expanding_string = g_string_new (""); - for (node = selection; node != NULL; node = node->next) { - uri = NULL; - if (NAUTILUS_IS_DESKTOP_ICON_FILE (node->data)) { - link = nautilus_desktop_icon_file_get_link (NAUTILUS_DESKTOP_ICON_FILE (node->data)); - if (link != NULL) { - location = nautilus_desktop_link_get_activation_location (link); - uri = g_file_get_uri (location); - g_object_unref (location); - g_object_unref (G_OBJECT (link)); - } - } else { - uri = nautilus_file_get_uri (NAUTILUS_FILE (node->data)); - } - if (uri == NULL) { - continue; - } - - if (get_paths) { - path = g_filename_from_uri (uri, NULL, NULL); - if (path != NULL) { - g_string_append (expanding_string, path); - g_free (path); - g_string_append (expanding_string, "\n"); - } - } else { - g_string_append (expanding_string, uri); - g_string_append (expanding_string, "\n"); - } - g_free (uri); - } - - result = expanding_string->str; - g_string_free (expanding_string, FALSE); - - return result; -} - -static char * -get_file_paths_as_newline_delimited_string (GList *selection) -{ - return get_file_paths_or_uris_as_newline_delimited_string (selection, TRUE); -} - -static char * -get_file_uris_as_newline_delimited_string (GList *selection) -{ - return get_file_paths_or_uris_as_newline_delimited_string (selection, FALSE); -} - -/* returns newly allocated strings for setting the environment variables */ -static void -get_strings_for_environment_variables (NautilusView *view, GList *selected_files, - char **file_paths, char **uris, char **uri) -{ - char *directory_uri; - - /* We need to check that the directory uri starts with "file:" since - * nautilus_directory_is_local returns FALSE for nfs. - */ - directory_uri = nautilus_directory_get_uri (view->details->model); - if (g_str_has_prefix (directory_uri, "file:") || - eel_uri_is_desktop (directory_uri) || - eel_uri_is_trash (directory_uri)) { - *file_paths = get_file_paths_as_newline_delimited_string (selected_files); - } else { - *file_paths = g_strdup (""); - } - g_free (directory_uri); - - *uris = get_file_uris_as_newline_delimited_string (selected_files); - - *uri = nautilus_directory_get_uri (view->details->model); - if (eel_uri_is_desktop (*uri)) { - g_free (*uri); - *uri = nautilus_get_desktop_directory_uri (); - } -} - -/* - * Set up some environment variables that scripts can use - * to take advantage of the current Nautilus state. - */ -static void -set_script_environment_variables (NautilusView *view, GList *selected_files) -{ - char *file_paths; - char *uris; - char *uri; - char *geometry_string; - - get_strings_for_environment_variables (view, selected_files, - &file_paths, &uris, &uri); - - g_setenv ("NAUTILUS_SCRIPT_SELECTED_FILE_PATHS", file_paths, TRUE); - g_free (file_paths); - - g_setenv ("NAUTILUS_SCRIPT_SELECTED_URIS", uris, TRUE); - g_free (uris); - - g_setenv ("NAUTILUS_SCRIPT_CURRENT_URI", uri, TRUE); - g_free (uri); - - geometry_string = eel_gtk_window_get_geometry_string - (GTK_WINDOW (nautilus_view_get_containing_window (view))); - g_setenv ("NAUTILUS_SCRIPT_WINDOW_GEOMETRY", geometry_string, TRUE); - g_free (geometry_string); -} - -/* Unset all the special script environment variables. */ -static void -unset_script_environment_variables (void) -{ - g_unsetenv ("NAUTILUS_SCRIPT_SELECTED_FILE_PATHS"); - g_unsetenv ("NAUTILUS_SCRIPT_SELECTED_URIS"); - g_unsetenv ("NAUTILUS_SCRIPT_CURRENT_URI"); - g_unsetenv ("NAUTILUS_SCRIPT_WINDOW_GEOMETRY"); -} - -static void -run_script (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - ScriptLaunchParameters *launch_parameters; - GdkScreen *screen; - GList *selected_files; - char *file_uri; - char *local_file_path; - char *quoted_path; - char *old_working_dir; - char **parameters; - - 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); - g_assert (local_file_path != NULL); - g_free (file_uri); - - quoted_path = g_shell_quote (local_file_path); - g_free (local_file_path); - - old_working_dir = change_to_view_directory (launch_parameters->directory_view); - - selected_files = nautilus_view_get_selection (launch_parameters->directory_view); - set_script_environment_variables (launch_parameters->directory_view, selected_files); - - parameters = get_file_names_as_parameter_array (selected_files, - launch_parameters->directory_view->details->model); - - screen = gtk_widget_get_screen (GTK_WIDGET (launch_parameters->directory_view)); - - DEBUG ("run_script, script_path=“%s” (omitting script parameters)", - local_file_path); - - nautilus_launch_application_from_command_array (screen, quoted_path, FALSE, - (const char * const *) parameters); - g_strfreev (parameters); - - nautilus_file_list_free (selected_files); - unset_script_environment_variables (); - g_chdir (old_working_dir); - g_free (old_working_dir); - g_free (quoted_path); -} - -static void -add_script_to_scripts_menus (NautilusView *view, - NautilusFile *file, - GMenu *menu) -{ - gchar *name; - GdkPixbuf *mimetype_icon; - gchar *action_name, *detailed_action_name; - ScriptLaunchParameters *launch_parameters; - GAction *action; - GMenuItem *menu_item; - - launch_parameters = script_launch_parameters_new (file, view); - - 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), - launch_parameters, - (GClosureNotify)script_launch_parameters_free, 0); - - 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); - - 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); - } - - g_menu_append_item (menu, menu_item); - - g_free (name); - g_free (action_name); - g_free (detailed_action_name); - g_object_unref (menu_item); -} - -static gboolean -directory_belongs_in_scripts_menu (const char *uri) -{ - int num_levels; - int i; - - if (!g_str_has_prefix (uri, scripts_directory_uri)) { - return FALSE; - } - - num_levels = 0; - for (i = scripts_directory_uri_length; uri[i] != '\0'; i++) { - if (uri[i] == '/') { - num_levels++; - } - } - - if (num_levels > MAX_MENU_LEVELS) { - return FALSE; - } - - return TRUE; -} - -static GMenu * -update_directory_in_scripts_menu (NautilusView *view, - NautilusDirectory *directory) -{ - GList *file_list, *filtered, *node; - GMenu *menu, *children_menu; - GMenuItem *menu_item; - gboolean any_scripts; - NautilusFile *file; - NautilusDirectory *dir; - char *uri; - gchar *file_name; - int num; - - g_return_val_if_fail (NAUTILUS_IS_VIEW (view), NULL); - g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), NULL); - - 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; 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_scripts_menu (uri)) { - dir = nautilus_directory_get_by_uri (uri); - add_directory_to_scripts_directory_list (view, dir); - - children_menu = update_directory_in_scripts_menu (view, dir); - - if (children_menu != NULL) { - file_name = nautilus_file_get_display_name (file); - menu_item = g_menu_item_new_submenu (file_name, - 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); - g_free (file_name); - } - - 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); - - if (!any_scripts) { - g_object_unref (menu); - menu = NULL; - } - - return menu; -} - - - -static void -update_scripts_menu (NautilusView *view) -{ - GList *sorted_copy, *node; - NautilusDirectory *directory; - GMenu *submenu; - char *uri; - - 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); - } - g_free (uri); - } - nautilus_directory_list_free (sorted_copy); - - 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); - g_object_unref (submenu); - } - - view->details->scripts_present = submenu != NULL; -} - -static void -create_template (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - - CreateTemplateParameters *parameters; - - parameters = user_data; - - nautilus_view_new_file (parameters->directory_view, NULL, parameters->file); -} - -static void -add_template_to_templates_menus (NautilusView *view, - NautilusFile *file, - GMenu *menu) -{ - char *tmp, *uri, *name; - GdkPixbuf *mimetype_icon; - char *action_name, *detailed_action_name; - CreateTemplateParameters *parameters; - 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); - action_name = nautilus_escape_action_name (uri, "template_"); - action = G_ACTION (g_simple_action_new (action_name, NULL)); - parameters = create_template_parameters_new (file, view); - - g_signal_connect_data (action, "activate", - 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); - - 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); - } - - g_menu_append_item (menu, menu_item); - - g_free (name); - g_free (uri); - g_free (action_name); - g_free (detailed_action_name); - g_object_unref (action); - g_object_unref (menu_item); -} - -static void -update_templates_directory (NautilusView *view) -{ - NautilusDirectory *templates_directory; - GList *node, *next; - char *templates_uri; - - for (node = view->details->templates_directory_list; node != NULL; node = next) { - next = node->next; - remove_directory_from_templates_directory_list (view, node->data); - } - - 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); - } -} - -static gboolean -directory_belongs_in_templates_menu (const char *templates_directory_uri, - const char *uri) -{ - int num_levels; - int i; - - if (templates_directory_uri == NULL) { - return FALSE; - } - - if (!g_str_has_prefix (uri, templates_directory_uri)) { - return FALSE; - } - - num_levels = 0; - for (i = strlen (templates_directory_uri); uri[i] != '\0'; i++) { - if (uri[i] == '/') { - num_levels++; - } - } - - if (num_levels > MAX_MENU_LEVELS) { - return FALSE; - } - - return TRUE; -} - -static GMenu * -update_directory_in_templates_menu (NautilusView *view, - NautilusDirectory *directory) -{ - GList *file_list, *filtered, *node; - GMenu *menu, *children_menu; - GMenuItem *menu_item; - gboolean any_templates; - NautilusFile *file; - NautilusDirectory *dir; - char *uri; - char *templates_directory_uri; - int num; - - g_return_val_if_fail (NAUTILUS_IS_VIEW (view), NULL); - g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), NULL); - - 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); - - num = 0; - 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); - - 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); - } - - nautilus_directory_unref (dir); - } - g_free (uri); - } else if (nautilus_file_can_read (file)) { - add_template_to_templates_menus (view, file, menu); - any_templates = TRUE; - } - } - - nautilus_file_list_free (file_list); - g_free (templates_directory_uri); - - if (!any_templates) { - g_object_unref (menu); - menu = NULL; - } - - return menu; -} - - - -static void -update_templates_menu (NautilusView *view) -{ - GList *sorted_copy, *node; - NautilusDirectory *directory; - GMenu *submenu; - char *uri; - char *templates_directory_uri; - - if (nautilus_should_use_templates_directory ()) { - templates_directory_uri = nautilus_get_templates_directory_uri (); - } else { - view->details->templates_present = FALSE; - return; - } - - - 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); - } - g_free (uri); - } - nautilus_directory_list_free (sorted_copy); - - 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); - g_object_unref (submenu); - } - - view->details->templates_present = submenu != NULL; - - g_free (templates_directory_uri); -} - - -static void -action_open_scripts_folder (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - NautilusView *view; - static GFile *location = NULL; - - if (location == NULL) { - location = g_file_new_for_uri (scripts_directory_uri); - } - - view = NAUTILUS_VIEW (user_data); - nautilus_window_slot_open_location (view->details->slot, location, 0); -} - -typedef struct _CopyCallbackData { - NautilusView *view; - GtkFileChooser *chooser; - GHashTable *locations; - GList *selection; - gboolean is_move; -} CopyCallbackData; - -static void -add_bookmark_for_uri (CopyCallbackData *data, - const char *uri) -{ - GError *error = NULL; - int count; - - count = GPOINTER_TO_INT (g_hash_table_lookup (data->locations, uri)); - if (count == 0) { - gtk_file_chooser_add_shortcut_folder_uri (data->chooser, - uri, - &error); - if (error != NULL) { - DEBUG ("Unable to add location '%s' to file selector: %s", uri, error->message); - g_clear_error (&error); - } - } - g_hash_table_replace (data->locations, g_strdup (uri), GINT_TO_POINTER (count + 1)); -} - -static void -remove_bookmark_for_uri (CopyCallbackData *data, - const char *uri) -{ - GError *error = NULL; - int count; - - count = GPOINTER_TO_INT (g_hash_table_lookup (data->locations, uri)); - if (count == 1) { - gtk_file_chooser_remove_shortcut_folder_uri (data->chooser, - uri, - &error); - if (error != NULL) { - DEBUG ("Unable to remove location '%s' to file selector: %s", uri, error->message); - g_clear_error (&error); - } - g_hash_table_remove (data->locations, uri); - } else { - g_hash_table_replace (data->locations, g_strdup (uri), GINT_TO_POINTER (count - 1)); - } -} - -static void -add_bookmarks_for_window_slot (CopyCallbackData *data, - NautilusWindowSlot *slot) -{ - char *uri; - - uri = nautilus_window_slot_get_location_uri (slot); - if (uri != NULL) { - add_bookmark_for_uri (data, uri); - } - g_free (uri); -} - -static void -remove_bookmarks_for_window_slot (CopyCallbackData *data, - NautilusWindowSlot *slot) -{ - char *uri; - - uri = nautilus_window_slot_get_location_uri (slot); - if (uri != NULL) { - remove_bookmark_for_uri (data, uri); - } - g_free (uri); -} - -static void -on_slot_location_changed (NautilusWindowSlot *slot, - const char *from, - const char *to, - CopyCallbackData *data) -{ - if (from != NULL) { - remove_bookmark_for_uri (data, from); - } - - if (to != NULL) { - add_bookmark_for_uri (data, to); - } -} - -static void -on_slot_added (NautilusWindow *window, - NautilusWindowSlot *slot, - CopyCallbackData *data) -{ - add_bookmarks_for_window_slot (data, slot); - g_signal_connect (slot, "location-changed", G_CALLBACK (on_slot_location_changed), data); -} - -static void -on_slot_removed (NautilusWindow *window, - NautilusWindowSlot *slot, - CopyCallbackData *data) -{ - remove_bookmarks_for_window_slot (data, slot); - g_signal_handlers_disconnect_by_func (slot, - G_CALLBACK (on_slot_location_changed), - data); -} - -static void -add_bookmarks_for_window (CopyCallbackData *data, - NautilusWindow *window) -{ - GList *s; - GList *slots; - - slots = nautilus_window_get_slots (window); - for (s = slots; s != NULL; s = s->next) { - NautilusWindowSlot *slot = s->data; - add_bookmarks_for_window_slot (data, slot); - g_signal_connect (slot, "location-changed", G_CALLBACK (on_slot_location_changed), data); - } - g_signal_connect (window, "slot-added", G_CALLBACK (on_slot_added), data); - g_signal_connect (window, "slot-removed", G_CALLBACK (on_slot_removed), data); -} - -static void -remove_bookmarks_for_window (CopyCallbackData *data, - NautilusWindow *window) -{ - GList *s; - GList *slots; - - slots = nautilus_window_get_slots (window); - for (s = slots; s != NULL; s = s->next) { - NautilusWindowSlot *slot = s->data; - remove_bookmarks_for_window_slot (data, slot); - g_signal_handlers_disconnect_by_func (slot, - G_CALLBACK (on_slot_location_changed), - data); - } - g_signal_handlers_disconnect_by_func (window, - G_CALLBACK (on_slot_added), - data); - g_signal_handlers_disconnect_by_func (window, - G_CALLBACK (on_slot_removed), - data); -} - -static void -on_app_window_added (GtkApplication *application, - GtkWindow *window, - CopyCallbackData *data) -{ - add_bookmarks_for_window (data, NAUTILUS_WINDOW (window)); -} - -static void -on_app_window_removed (GtkApplication *application, - GtkWindow *window, - CopyCallbackData *data) -{ - remove_bookmarks_for_window (data, NAUTILUS_WINDOW (window)); -} - -static void -copy_data_free (CopyCallbackData *data) -{ - NautilusApplication *application; - GList *windows; - GList *w; - - application = NAUTILUS_APPLICATION (g_application_get_default ()); - g_signal_handlers_disconnect_by_func (application, - G_CALLBACK (on_app_window_added), - data); - g_signal_handlers_disconnect_by_func (application, - G_CALLBACK (on_app_window_removed), - data); - - windows = nautilus_application_get_windows (application); - for (w = windows; w != NULL; w = w->next) { - NautilusWindow *window = w->data; - GList *slots; - GList *s; - - slots = nautilus_window_get_slots (window); - for (s = slots; s != NULL; s = s->next) { - NautilusWindowSlot *slot = s->data; - g_signal_handlers_disconnect_by_func (slot, G_CALLBACK (on_slot_location_changed), data); - } - g_signal_handlers_disconnect_by_func (window, G_CALLBACK (on_slot_added), data); - g_signal_handlers_disconnect_by_func (window, G_CALLBACK (on_slot_removed), data); - } - - nautilus_file_list_free (data->selection); - g_hash_table_destroy (data->locations); - g_free (data); -} - -static gboolean -uri_is_parent_of_selection (GList *selection, - const char *uri) -{ - gboolean found; - GList *l; - GFile *file; - - found = FALSE; - - file = g_file_new_for_uri (uri); - for (l = selection; !found && l != NULL; l = l->next) { - GFile *parent; - parent = nautilus_file_get_parent_location (l->data); - found = g_file_equal (file, parent); - g_object_unref (parent); - } - g_object_unref (file); - return found; -} - -static void -on_destination_dialog_folder_changed (GtkFileChooser *chooser, - gpointer user_data) -{ - CopyCallbackData *copy_data = user_data; - char *uri; - gboolean found; - - uri = gtk_file_chooser_get_current_folder_uri (chooser); - found = uri_is_parent_of_selection (copy_data->selection, uri); - gtk_dialog_set_response_sensitive (GTK_DIALOG (chooser), GTK_RESPONSE_OK, !found); - g_free (uri); -} - -static void -on_destination_dialog_response (GtkDialog *dialog, - gint response_id, - gpointer user_data) -{ - CopyCallbackData *copy_data = user_data; - - if (response_id == GTK_RESPONSE_OK) { - char *target_uri; - GList *uris, *l; - - target_uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog)); - - uris = NULL; - for (l = copy_data->selection; l != NULL; l = l->next) { - uris = g_list_prepend (uris, - nautilus_file_get_uri ((NautilusFile *) l->data)); - } - uris = g_list_reverse (uris); - - nautilus_view_move_copy_items (copy_data->view, uris, NULL, target_uri, - copy_data->is_move ? GDK_ACTION_MOVE : GDK_ACTION_COPY, - 0, 0); - - g_list_free_full (uris, g_free); - g_free (target_uri); - } - - copy_data_free (copy_data); - gtk_widget_destroy (GTK_WIDGET (dialog)); -} - -static gboolean -destination_dialog_filter_cb (const GtkFileFilterInfo *filter_info, - gpointer user_data) -{ - GList *selection = user_data; - GList *l; - - for (l = selection; l != NULL; l = l->next) { - char *uri; - uri = nautilus_file_get_uri (l->data); - if (strcmp (uri, filter_info->uri) == 0) { - g_free (uri); - return FALSE; - } - g_free (uri); - } - - return TRUE; -} - -static GList * -get_selected_folders (GList *selection) -{ - GList *folders; - GList *l; - - folders = NULL; - for (l = selection; l != NULL; l = l->next) { - if (nautilus_file_is_directory (l->data)) - folders = g_list_prepend (folders, nautilus_file_ref (l->data)); - } - return g_list_reverse (folders); -} - -static void -add_window_location_bookmarks (CopyCallbackData *data) -{ - NautilusApplication *application; - GList *windows; - GList *w; - - application = NAUTILUS_APPLICATION (g_application_get_default ()); - windows = nautilus_application_get_windows (application); - g_signal_connect (application, "window-added", G_CALLBACK (on_app_window_added), data); - g_signal_connect (application, "window-removed", G_CALLBACK (on_app_window_removed), data); - - for (w = windows; w != NULL; w = w->next) { - NautilusWindow *window = w->data; - add_bookmarks_for_window (data, window); - } -} - -static void -copy_or_move_selection (NautilusView *view, - gboolean is_move) -{ - GtkWidget *dialog; - char *uri; - CopyCallbackData *copy_data; - GList *selection; - const gchar *title; - - if (is_move) { - title = _("Select Move Destination"); - } else { - title = _("Select Copy Destination"); - } - - selection = nautilus_view_get_selection_for_file_transfer (view); - - dialog = gtk_file_chooser_dialog_new (title, - GTK_WINDOW (nautilus_view_get_window (view)), - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, - _("_Cancel"), GTK_RESPONSE_CANCEL, - _("_Select"), GTK_RESPONSE_OK, - NULL); - gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE); - gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); - - copy_data = g_new0 (CopyCallbackData, 1); - copy_data->view = view; - copy_data->selection = selection; - copy_data->is_move = is_move; - copy_data->chooser = GTK_FILE_CHOOSER (dialog); - copy_data->locations = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - - add_window_location_bookmarks (copy_data); - - if (selection != NULL) { - GtkFileFilter *filter; - GList *folders; - - folders = get_selected_folders (selection); - - filter = gtk_file_filter_new (); - gtk_file_filter_add_custom (filter, - GTK_FILE_FILTER_URI, - destination_dialog_filter_cb, - folders, - (GDestroyNotify)nautilus_file_list_free); - gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter); - } - - uri = nautilus_directory_get_uri (view->details->model); - gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), uri); - g_free (uri); - g_signal_connect (dialog, "current-folder-changed", - G_CALLBACK (on_destination_dialog_folder_changed), - copy_data); - g_signal_connect (dialog, "response", - G_CALLBACK (on_destination_dialog_response), - copy_data); - - gtk_widget_show_all (dialog); -} - -static void -copy_or_cut_files (NautilusView *view, - GList *clipboard_contents, - gboolean cut) -{ - NautilusClipboardInfo info; - GtkTargetList *target_list; - GtkTargetEntry *targets; - int n_targets; - - info.files = clipboard_contents; - info.cut = cut; - - target_list = gtk_target_list_new (NULL, 0); - gtk_target_list_add (target_list, copied_files_atom, 0, 0); - gtk_target_list_add_uri_targets (target_list, 0); - gtk_target_list_add_text_targets (target_list, 0); - - targets = gtk_target_table_new_from_list (target_list, &n_targets); - gtk_target_list_unref (target_list); - - gtk_clipboard_set_with_data (nautilus_clipboard_get (GTK_WIDGET (view)), - targets, n_targets, - nautilus_get_clipboard_callback, nautilus_clear_clipboard_callback, - NULL); - gtk_target_table_free (targets, n_targets); - - nautilus_clipboard_monitor_set_clipboard_info (nautilus_clipboard_monitor_get (), &info); -} - -static void -action_copy (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - NautilusView *view; - GList *selection; - - view = NAUTILUS_VIEW (user_data); - - selection = nautilus_view_get_selection_for_file_transfer (view); - copy_or_cut_files (view, selection, FALSE); - nautilus_file_list_free (selection); -} - -static void -action_cut (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - NautilusView *view; - GList *selection; - - view = NAUTILUS_VIEW (user_data); - - selection = nautilus_view_get_selection_for_file_transfer (view); - copy_or_cut_files (view, selection, TRUE); - nautilus_file_list_free (selection); -} - -static void -action_copy_to (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - NautilusView *view; - - view = NAUTILUS_VIEW (user_data); - copy_or_move_selection (view, FALSE); -} - -static void -action_move_to (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - NautilusView *view; - - view = NAUTILUS_VIEW (user_data); - copy_or_move_selection (view, TRUE); -} - -typedef struct { - NautilusView *view; - NautilusFile *target; -} PasteIntoData; - -static void -paste_into_clipboard_received_callback (GtkClipboard *clipboard, - GtkSelectionData *selection_data, - gpointer callback_data) -{ - PasteIntoData *data; - NautilusView *view; - char *directory_uri; - - data = (PasteIntoData *) callback_data; - - view = NAUTILUS_VIEW (data->view); - - if (view->details->slot != NULL) { - directory_uri = nautilus_file_get_activation_uri (data->target); - - paste_clipboard_data (view, selection_data, directory_uri); - - g_free (directory_uri); - } - - g_object_unref (view); - nautilus_file_unref (data->target); - g_free (data); -} - -static void -paste_into (NautilusView *view, - NautilusFile *target) -{ - PasteIntoData *data; - - g_assert (NAUTILUS_IS_VIEW (view)); - g_assert (NAUTILUS_IS_FILE (target)); - - data = g_new (PasteIntoData, 1); - - data->view = g_object_ref (view); - data->target = nautilus_file_ref (target); - - gtk_clipboard_request_contents (nautilus_clipboard_get (GTK_WIDGET (view)), - copied_files_atom, - paste_into_clipboard_received_callback, - data); -} - -static void -action_paste_files_into (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - NautilusView *view; - GList *selection; - - view = NAUTILUS_VIEW (user_data); - selection = nautilus_view_get_selection (view); - if (selection != NULL) { - paste_into (view, NAUTILUS_FILE (selection->data)); - nautilus_file_list_free (selection); - } - -} - -static void -invoke_external_bulk_rename_utility (NautilusView *view, - GList *selection) -{ - GString *cmd; - char *parameter; - char *quoted_parameter; - char *bulk_rename_tool; - GList *walk; - NautilusFile *file; - - /* assemble command line */ - bulk_rename_tool = get_bulk_rename_tool (); - cmd = g_string_new (bulk_rename_tool); - g_free (bulk_rename_tool); - for (walk = selection; walk; walk = walk->next) { - file = walk->data; - parameter = nautilus_file_get_uri (file); - quoted_parameter = g_shell_quote (parameter); - g_free (parameter); - cmd = g_string_append (cmd, " "); - cmd = g_string_append (cmd, quoted_parameter); - g_free (quoted_parameter); - } - - /* spawning and error handling */ - nautilus_launch_application_from_command (gtk_widget_get_screen (GTK_WIDGET (view)), - cmd->str, FALSE, NULL); - g_string_free (cmd, TRUE); -} - -static void -real_action_rename (NautilusView *view, - gboolean select_all) -{ - NautilusFile *file; - GList *selection; - - g_assert (NAUTILUS_IS_VIEW (view)); - - selection = nautilus_view_get_selection (view); - - if (selection_not_empty_in_menu_callback (view, selection)) { - /* If there is more than one file selected, invoke a batch renamer */ - if (selection->next != NULL) { - if (have_bulk_rename_tool ()) { - invoke_external_bulk_rename_utility (view, selection); - } - } else { - file = NAUTILUS_FILE (selection->data); - if (!select_all) { - /* directories don't have a file extension, so - * they are always pre-selected as a whole */ - select_all = nautilus_file_is_directory (file); - } - nautilus_view_rename_file_popover_new (view, file); - } - } - - nautilus_file_list_free (selection); -} - -static void -action_rename (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - real_action_rename (NAUTILUS_VIEW (user_data), FALSE); -} - -#define BG_KEY_PRIMARY_COLOR "primary-color" -#define BG_KEY_SECONDARY_COLOR "secondary-color" -#define BG_KEY_COLOR_TYPE "color-shading-type" -#define BG_KEY_PICTURE_PLACEMENT "picture-options" -#define BG_KEY_PICTURE_URI "picture-uri" - -static void -set_uri_as_wallpaper (const char *uri) -{ - GSettings *settings; - - settings = gnome_background_preferences; - - g_settings_delay (settings); - - if (uri == NULL) - uri = ""; - - g_settings_set_string (settings, BG_KEY_PICTURE_URI, uri); - g_settings_set_string (settings, BG_KEY_PRIMARY_COLOR, "#000000"); - g_settings_set_string (settings, BG_KEY_SECONDARY_COLOR, "#000000"); - g_settings_set_enum (settings, BG_KEY_COLOR_TYPE, G_DESKTOP_BACKGROUND_SHADING_SOLID); - g_settings_set_enum (settings, BG_KEY_PICTURE_PLACEMENT, G_DESKTOP_BACKGROUND_STYLE_ZOOM); - - /* Apply changes atomically. */ - g_settings_apply (settings); -} - -static void -wallpaper_copy_done_callback (GHashTable *debuting_files, - gboolean success, - gpointer data) -{ - GHashTableIter iter; - gpointer key, value; - - g_hash_table_iter_init (&iter, debuting_files); - while (g_hash_table_iter_next (&iter, &key, &value)) { - char *uri; - uri = g_file_get_uri (G_FILE (key)); - set_uri_as_wallpaper (uri); - g_free (uri); - break; - } -} - -static gboolean -can_set_wallpaper (GList *selection) -{ - NautilusFile *file; - - if (g_list_length (selection) != 1) { - return FALSE; - } - - file = NAUTILUS_FILE (selection->data); - if (!nautilus_file_is_mime_type (file, "image/*")) { - return FALSE; - } - - /* FIXME: check file size? */ - - return TRUE; -} - -static void -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 (user_data)); - - selection = nautilus_view_get_selection (user_data); - - if (can_set_wallpaper (selection) - && selection_not_empty_in_menu_callback (user_data, selection)) { - NautilusFile *file; - char *target_uri; - GList *uris; - GFile *parent; - GFile *target; - - file = NAUTILUS_FILE (selection->data); - - parent = g_file_new_for_path (g_get_user_special_dir (G_USER_DIRECTORY_PICTURES)); - target = g_file_get_child (parent, "Wallpapers"); - g_object_unref (parent); - g_file_make_directory_with_parents (target, NULL, NULL); - target_uri = g_file_get_uri (target); - g_object_unref (target); - uris = g_list_prepend (NULL, nautilus_file_get_uri (file)); - nautilus_file_operations_copy_move (uris, - NULL, - target_uri, - GDK_ACTION_COPY, - GTK_WIDGET (user_data), - wallpaper_copy_done_callback, - NULL); - g_free (target_uri); - g_list_free_full (uris, g_free); - } - - nautilus_file_list_free (selection); -} - -static void -file_mount_callback (NautilusFile *file, - GFile *result_location, - GError *error, - gpointer callback_data) -{ - NautilusView *view; - - view = NAUTILUS_VIEW (callback_data); - - if (error != NULL && - (error->domain != G_IO_ERROR || - (error->code != G_IO_ERROR_CANCELLED && - error->code != G_IO_ERROR_FAILED_HANDLED && - error->code != G_IO_ERROR_ALREADY_MOUNTED))) { - char *text; - char *name; - name = nautilus_file_get_display_name (file); - /* Translators: %s is a file name formatted for display */ - text = g_strdup_printf (_("Unable to access “%s”"), name); - eel_show_error_dialog (text, error->message, - GTK_WINDOW (nautilus_view_get_window (view))); - g_free (text); - g_free (name); - } -} - -static void -file_unmount_callback (NautilusFile *file, - GFile *result_location, - GError *error, - gpointer callback_data) -{ - NautilusView *view; - - view = NAUTILUS_VIEW (callback_data); - g_object_unref (view); - - if (error != NULL && - (error->domain != G_IO_ERROR || - (error->code != G_IO_ERROR_CANCELLED && - error->code != G_IO_ERROR_FAILED_HANDLED))) { - char *text; - char *name; - name = nautilus_file_get_display_name (file); - /* Translators: %s is a file name formatted for display */ - text = g_strdup_printf (_("Unable to remove “%s”"), name); - eel_show_error_dialog (text, error->message, - GTK_WINDOW (nautilus_view_get_window (view))); - g_free (text); - g_free (name); - } -} - -static void -file_eject_callback (NautilusFile *file, - GFile *result_location, - GError *error, - gpointer callback_data) -{ - NautilusView *view; - - view = NAUTILUS_VIEW (callback_data); - g_object_unref (view); - - if (error != NULL && - (error->domain != G_IO_ERROR || - (error->code != G_IO_ERROR_CANCELLED && - error->code != G_IO_ERROR_FAILED_HANDLED))) { - char *text; - char *name; - name = nautilus_file_get_display_name (file); - /* Translators: %s is a file name formatted for display */ - text = g_strdup_printf (_("Unable to eject “%s”"), name); - eel_show_error_dialog (text, error->message, - GTK_WINDOW (nautilus_view_get_window (view))); - g_free (text); - g_free (name); - } -} - -static void -file_stop_callback (NautilusFile *file, - GFile *result_location, - GError *error, - gpointer callback_data) -{ - NautilusView *view; - - view = NAUTILUS_VIEW (callback_data); - - if (error != NULL && - (error->domain != G_IO_ERROR || - (error->code != G_IO_ERROR_CANCELLED && - error->code != G_IO_ERROR_FAILED_HANDLED))) { - eel_show_error_dialog (_("Unable to stop drive"), - error->message, - GTK_WINDOW (nautilus_view_get_window (view))); - } -} - -static void -action_mount_volume (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - NautilusFile *file; - GList *selection, *l; - NautilusView *view; - GMountOperation *mount_op; - - view = NAUTILUS_VIEW (user_data); - - selection = nautilus_view_get_selection (view); - for (l = selection; l != NULL; l = l->next) { - file = NAUTILUS_FILE (l->data); - - if (nautilus_file_can_mount (file)) { - mount_op = gtk_mount_operation_new (nautilus_view_get_containing_window (view)); - g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION); - nautilus_file_mount (file, mount_op, NULL, - file_mount_callback, - view); - g_object_unref (mount_op); - } - } - nautilus_file_list_free (selection); -} - -static void -action_unmount_volume (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - NautilusFile *file; - GList *selection, *l; - NautilusView *view; - - view = NAUTILUS_VIEW (user_data); - - selection = nautilus_view_get_selection (view); - - for (l = selection; l != NULL; l = l->next) { - file = NAUTILUS_FILE (l->data); - if (nautilus_file_can_unmount (file)) { - GMountOperation *mount_op; - mount_op = gtk_mount_operation_new (nautilus_view_get_containing_window (view)); - nautilus_file_unmount (file, mount_op, NULL, - file_unmount_callback, g_object_ref (view)); - g_object_unref (mount_op); - } - } - nautilus_file_list_free (selection); -} - -static void -action_eject_volume (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - NautilusFile *file; - GList *selection, *l; - NautilusView *view; - - view = NAUTILUS_VIEW (user_data); - - selection = nautilus_view_get_selection (view); - for (l = selection; l != NULL; l = l->next) { - file = NAUTILUS_FILE (l->data); - - if (nautilus_file_can_eject (file)) { - GMountOperation *mount_op; - mount_op = gtk_mount_operation_new (nautilus_view_get_containing_window (view)); - nautilus_file_eject (file, mount_op, NULL, - file_eject_callback, g_object_ref (view)); - g_object_unref (mount_op); - } - } - nautilus_file_list_free (selection); -} - -static void -file_start_callback (NautilusFile *file, - GFile *result_location, - GError *error, - gpointer callback_data) -{ - NautilusView *view; - - view = NAUTILUS_VIEW (callback_data); - - if (error != NULL && - (error->domain != G_IO_ERROR || - (error->code != G_IO_ERROR_CANCELLED && - error->code != G_IO_ERROR_FAILED_HANDLED && - error->code != G_IO_ERROR_ALREADY_MOUNTED))) { - char *text; - char *name; - name = nautilus_file_get_display_name (file); - /* Translators: %s is a file name formatted for display */ - text = g_strdup_printf (_("Unable to start “%s”"), name); - eel_show_error_dialog (text, error->message, - GTK_WINDOW (nautilus_view_get_window (view))); - g_free (text); - g_free (name); - } -} - -static void -action_start_volume (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - NautilusFile *file; - GList *selection, *l; - NautilusView *view; - GMountOperation *mount_op; - - view = NAUTILUS_VIEW (user_data); - - selection = nautilus_view_get_selection (view); - for (l = selection; l != NULL; l = l->next) { - file = NAUTILUS_FILE (l->data); - - if (nautilus_file_can_start (file) || nautilus_file_can_start_degraded (file)) { - mount_op = gtk_mount_operation_new (nautilus_view_get_containing_window (view)); - nautilus_file_start (file, mount_op, NULL, - file_start_callback, view); - g_object_unref (mount_op); - } - } - nautilus_file_list_free (selection); -} - -static void -action_stop_volume (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - NautilusFile *file; - GList *selection, *l; - NautilusView *view; - - view = NAUTILUS_VIEW (user_data); - - selection = nautilus_view_get_selection (view); - for (l = selection; l != NULL; l = l->next) { - file = NAUTILUS_FILE (l->data); - - if (nautilus_file_can_stop (file)) { - GMountOperation *mount_op; - mount_op = gtk_mount_operation_new (nautilus_view_get_containing_window (view)); - nautilus_file_stop (file, mount_op, NULL, - file_stop_callback, view); - g_object_unref (mount_op); - } - } - nautilus_file_list_free (selection); -} - -static void -action_detect_media (GSimpleAction *action, - GVariant *state, - gpointer user_data) -{ - NautilusFile *file; - GList *selection, *l; - NautilusView *view; - - view = NAUTILUS_VIEW (user_data); - - selection = nautilus_view_get_selection (view); - for (l = selection; l != NULL; l = l->next) { - file = NAUTILUS_FILE (l->data); - - if (nautilus_file_can_poll_for_media (file) && !nautilus_file_is_media_check_automatic (file)) { - nautilus_file_poll_for_media (file); - } - } - nautilus_file_list_free (selection); -} - -const GActionEntry view_entries[] = { - /* Toolbar menu */ - { "zoom-in", action_zoom_in }, - { "zoom-out", action_zoom_out }, - { "zoom-default", action_zoom_default }, - { "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-from-trash", action_delete }, - /* We separate the shortcut and the menu item since we want the shortcut - * to always be available, but we don't want the menu item shown if not - * completely necesary. Since the visibility of the menu item is based on - * the action enability, we need to split the actions for the menu and the - * shortcut. */ - { "delete-permanently-shortcut", action_delete }, - { "delete-permanently-menu-item", action_delete }, - { "remove-from-recent", action_remove_from_recent }, - { "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 }, - /* 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 }, - /* Warning dialog for the change of the shorcut to move to trash */ - { "show-move-to-trash-shortcut-changed-dialog", action_show_move_to_trash_shortcut_changed_dialog } -}; - -static gboolean -can_paste_into_file (NautilusFile *file) -{ - if (nautilus_file_is_directory (file) && - nautilus_file_can_write (file)) { - return TRUE; - } - if (nautilus_file_has_activation_uri (file)) { - GFile *location; - NautilusFile *activation_file; - gboolean res; - - location = nautilus_file_get_activation_location (file); - activation_file = nautilus_file_get (location); - g_object_unref (location); - - /* The target location might not have data for it read yet, - and we can't want to do sync I/O, so treat the unknown - case as can-write */ - res = (nautilus_file_get_file_type (activation_file) == G_FILE_TYPE_UNKNOWN) || - (nautilus_file_get_file_type (activation_file) == G_FILE_TYPE_DIRECTORY && - nautilus_file_can_write (activation_file)); - - nautilus_file_unref (activation_file); - - return res; - } - - return FALSE; -} - -static void -clipboard_targets_received (GtkClipboard *clipboard, - GdkAtom *targets, - int n_targets, - gpointer user_data) -{ - NautilusView *view; - gboolean can_paste; - int i; - GAction *action; - - view = NAUTILUS_VIEW (user_data); - can_paste = FALSE; - - if (view->details->slot == NULL || - !view->details->active) { - /* We've been destroyed or became inactive since call */ - g_object_unref (view); - return; - } - - if (targets) { - for (i = 0; i < n_targets; i++) { - if (targets[i] == copied_files_atom) { - can_paste = TRUE; - } - } - } - - 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)); - - action = g_action_map_lookup_action (G_ACTION_MAP (view->details->view_action_group), - "paste-into"); - - g_simple_action_set_enabled (G_SIMPLE_ACTION (action), - can_paste && g_action_get_enabled (action)); - - g_object_unref (view); -} - -static void -file_should_show_foreach (NautilusFile *file, - gboolean *show_mount, - gboolean *show_unmount, - gboolean *show_eject, - gboolean *show_start, - gboolean *show_stop, - gboolean *show_poll, - GDriveStartStopType *start_stop_type) -{ - *show_mount = FALSE; - *show_unmount = FALSE; - *show_eject = FALSE; - *show_start = FALSE; - *show_stop = FALSE; - *show_poll = FALSE; - - if (nautilus_file_can_eject (file)) { - *show_eject = TRUE; - } - - if (nautilus_file_can_mount (file)) { - *show_mount = TRUE; - } - - if (nautilus_file_can_start (file) || nautilus_file_can_start_degraded (file)) { - *show_start = TRUE; - } - - if (nautilus_file_can_stop (file)) { - *show_stop = TRUE; - } - - /* Dot not show both Unmount and Eject/Safe Removal; too confusing to - * have too many menu entries */ - if (nautilus_file_can_unmount (file) && !*show_eject && !*show_stop) { - *show_unmount = TRUE; - } - - if (nautilus_file_can_poll_for_media (file) && !nautilus_file_is_media_check_automatic (file)) { - *show_poll = TRUE; - } - - *start_stop_type = nautilus_file_get_start_stop_type (file); -} - -static gboolean -can_restore_from_trash (GList *files) -{ - NautilusFile *original_file; - NautilusFile *original_dir; - GHashTable *original_dirs_hash; - GList *original_dirs; - gboolean can_restore; - - original_file = NULL; - original_dir = NULL; - original_dirs = NULL; - original_dirs_hash = NULL; - - if (files != NULL) { - if (g_list_length (files) == 1) { - original_file = nautilus_file_get_trash_original_file (files->data); - } else { - original_dirs_hash = nautilus_trashed_files_get_original_directories (files, NULL); - if (original_dirs_hash != NULL) { - original_dirs = g_hash_table_get_keys (original_dirs_hash); - if (g_list_length (original_dirs) == 1) { - original_dir = nautilus_file_ref (NAUTILUS_FILE (original_dirs->data)); - } - } - } - } - - can_restore = original_file != NULL || original_dirs != NULL; - - nautilus_file_unref (original_file); - nautilus_file_unref (original_dir); - g_list_free (original_dirs); - - if (original_dirs_hash != NULL) { - g_hash_table_destroy (original_dirs_hash); - } - return can_restore; -} - -static void -clipboard_changed_callback (NautilusClipboardMonitor *monitor, NautilusView *view) -{ - /* Update paste menu item */ - nautilus_view_update_context_menus (view); -} - -static gboolean -can_delete_all (GList *files) -{ - NautilusFile *file; - GList *l; - - for (l = files; l != NULL; l = l->next) { - file = l->data; - if (!nautilus_file_can_delete (file)) { - return FALSE; - } - } - return TRUE; -} - -static gboolean -can_trash_all (GList *files) -{ - NautilusFile *file; - GList *l; - - for (l = files; l != NULL; l = l->next) { - file = l->data; - if (!nautilus_file_can_trash (file)) { - return FALSE; - } - } - return TRUE; -} - -static gboolean -all_in_trash (GList *files) -{ - NautilusFile *file; - GList *l; - - for (l = files; l != NULL; l = l->next) { - file = l->data; - if (!nautilus_file_is_in_trash (file)) { - return FALSE; - } - } - 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_actions_state (NautilusView *view) -{ - GList *selection, *l; - NautilusFile *file; - gint selection_count; - 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_app, show_run; - gboolean item_opens_in_view; - gboolean is_read_only; - GAction *action; - GAppInfo *app; - 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; - - 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 = nautilus_view_is_search (view); - selection_is_read_only = selection_count == 1 && - (!nautilus_file_can_write (NAUTILUS_FILE (selection->data)) && - !nautilus_file_has_activation_uri (NAUTILUS_FILE (selection->data))); - selection_all_in_trash = all_in_trash (selection); - - 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) && - selection_count != 0 && - !selection_contains_special_link && - !selection_contains_desktop_or_home_dir; - can_trash_files = - can_trash_all (selection) && - selection_count != 0 && - !selection_contains_special_link && - !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; - 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) { - g_simple_action_set_enabled (G_SIMPLE_ACTION (action), - have_bulk_rename_tool ()); - } else { - g_simple_action_set_enabled (G_SIMPLE_ACTION (action), - selection_count == 1 && - nautilus_view_can_rename_file (view, selection->data)); - } - - action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), - "open-item-location"); - - 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; - - file = NAUTILUS_FILE (selection->data); - - if (!nautilus_mime_file_opens_in_external_app (file)) { - show_app = FALSE; - } - - if (!nautilus_mime_file_launches (file)) { - show_run = FALSE; - } - - if (!nautilus_mime_file_opens_in_view (file)) { - item_opens_in_view = FALSE; - } - - if (!show_app && !show_run && !item_opens_in_view) { - break; - } - } - - /* Open With <App> menu item */ - app = NULL; - if (show_app) { - app = nautilus_mime_get_default_application_for_files (selection); - } - - 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 || - (selection_count > 0 && - nautilus_file_is_directory (NAUTILUS_FILE (selection->data)))); - - 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-from-trash"); - g_simple_action_set_enabled (G_SIMPLE_ACTION (action), - can_delete_files && selection_all_in_trash); - - action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), - "delete-permanently-shortcut"); - g_simple_action_set_enabled (G_SIMPLE_ACTION (action), - can_delete_files); - - action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), - "delete-permanently-menu-item"); - g_simple_action_set_enabled (G_SIMPLE_ACTION (action), - can_delete_files && !can_trash_files && - !selection_all_in_trash && !selection_contains_recent); - - action = g_action_map_lookup_action (G_ACTION_MAP (view_action_group), - "remove-from-recent"); - g_simple_action_set_enabled (G_SIMPLE_ACTION (action), - selection_contains_recent && selection_count > 0); - - 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; - - 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_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); - - /* 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); - - 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)); - - /* Toolbar menu actions */ - 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)); - - NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->update_actions_state (view); -} - -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; - - selection = nautilus_view_get_selection (view); - selection_count = g_list_length (selection); - - 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); - start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN; - item_label = g_strdup_printf (ngettext ("New Folder with Selection (%'d Item)", - "New Folder with Selection (%'d Items)", - selection_count), - 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; - - file = NAUTILUS_FILE (selection->data); - - if (!nautilus_mime_file_opens_in_external_app (file)) { - show_app = FALSE; - } - - if (!nautilus_mime_file_launches (file)) { - show_run = FALSE; - } - - if (!nautilus_mime_file_opens_in_view (file)) { - item_opens_in_view = FALSE; - } - - if (!show_app && !show_run && !item_opens_in_view) { - break; - } - } - - item_label = NULL; - app = NULL; - app_icon = NULL; - if (show_app) { - app = nautilus_mime_get_default_application_for_files (selection); - } - - char *escaped_app; - - 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); - - 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 { - item_label = g_strdup (_("Open")); - } - - 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); - - nautilus_gmenu_add_item_in_submodel (view->details->selection_menu, - menu_item, - "open-with-default-application-section", - FALSE); - - 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; - - 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_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; - } - - 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; - } - - 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 (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); - } - - update_scripts_menu (view); -} - -static void -update_background_menu (NautilusView *view) -{ - - if (nautilus_view_supports_creating_files (view) && - !showing_recent_directory (view)) - update_templates_menu (view); -} - -static void -real_update_context_menus (NautilusView *view) -{ - g_clear_object (&view->details->background_menu); - g_clear_object (&view->details->selection_menu); - - 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"))); - g_object_unref (builder); - - update_selection_menu (view); - update_background_menu (view); - update_extensions_menus (view); - - nautilus_view_update_actions_state (view); -} - -/* 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)); - - NAUTILUS_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->update_context_menus (view); -} - -static void -nautilus_view_reset_view_menu (NautilusView *view) -{ - GActionGroup *view_action_group; - GVariant *variant; - GVariantIter iter; - gboolean show_sort_trash, show_sort_search, show_sort_access, show_sort_modification, enable_sort; - const gchar *hint; - - view_action_group = nautilus_view_get_action_group (view); - - gtk_widget_set_visible (view->details->visible_columns, - g_action_group_has_action (view_action_group, "visible-columns")); - - enable_sort = g_action_group_get_action_enabled (view_action_group, "sort"); - show_sort_trash = show_sort_search = show_sort_modification = show_sort_access = FALSE; - gtk_widget_set_visible (view->details->sort_menu, enable_sort); - - if (enable_sort) { - variant = g_action_group_get_action_state_hint (view_action_group, "sort"); - g_variant_iter_init (&iter, variant); - - while (g_variant_iter_next (&iter, "&s", &hint)) { - if (g_strcmp0 (hint, "trash-time") == 0) - show_sort_trash = TRUE; - if (g_strcmp0 (hint, "search-relevance") == 0) - show_sort_search = TRUE; - } - - g_variant_unref (variant); - } - - gtk_widget_set_visible (view->details->sort_trash_time, show_sort_trash); - gtk_widget_set_visible (view->details->sort_search_relevance, show_sort_search); - - variant = g_action_group_get_action_state (view_action_group, "zoom-to-level"); - gtk_adjustment_set_value (view->details->zoom_adjustment, - g_variant_get_int32 (variant)); - g_variant_unref (variant); -} - -/* Convenience function to reset the menus owned by the view but managed on - * the toolbar, and update them with the current state. - * 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) -{ - NautilusWindow *window; - - g_assert (NAUTILUS_IS_VIEW (view)); - - /* Don't update after destroy (#349551), - * or if we are not active. - */ - if (view->details->slot == NULL || - !view->details->active) { - return; - } - window = nautilus_view_get_window (view); - nautilus_window_reset_menus (window); - - nautilus_view_reset_view_menu (view); - nautilus_view_update_actions_state (view); -} - -/** - * nautilus_view_pop_up_selection_context_menu - * - * Pop up a context menu appropriate to the selected items. - * @view: NautilusView of interest. - * @event: The event that triggered this context menu. - * - **/ -void -nautilus_view_pop_up_selection_context_menu (NautilusView *view, - GdkEventButton *event) -{ - g_assert (NAUTILUS_IS_VIEW (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, event); - - nautilus_pop_up_context_menu (GTK_WIDGET (view), view->details->selection_menu, event); -} - -/** - * nautilus_view_pop_up_background_context_menu - * - * Pop up a context menu appropriate to the view globally at the last right click location. - * @view: NautilusView of interest. - * - **/ -void -nautilus_view_pop_up_background_context_menu (NautilusView *view, - GdkEventButton *event) -{ - g_assert (NAUTILUS_IS_VIEW (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, event); - - nautilus_pop_up_context_menu (GTK_WIDGET (view), view->details->background_menu, event); -} - -static void -schedule_update_context_menus (NautilusView *view) -{ - g_assert (NAUTILUS_IS_VIEW (view)); - - /* Don't schedule updates after destroy (#349551), - * or if we are not active. - */ - if (view->details->slot == NULL || - !view->details->active) { - return; - } - - /* Schedule a menu update with the current update interval */ - 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); - } -} - -static void -remove_update_status_idle_callback (NautilusView *view) -{ - if (view->details->update_status_idle_id != 0) { - g_source_remove (view->details->update_status_idle_id); - view->details->update_status_idle_id = 0; - } -} - -static gboolean -update_status_idle_callback (gpointer data) -{ - NautilusView *view; - - view = NAUTILUS_VIEW (data); - nautilus_view_display_selection_info (view); - view->details->update_status_idle_id = 0; - return FALSE; -} - -static void -schedule_update_status (NautilusView *view) -{ - g_assert (NAUTILUS_IS_VIEW (view)); - - /* Make sure we haven't already destroyed it */ - if (view->details->slot == NULL) { - return; - } - - if (view->details->loading) { - /* Don't update status bar while loading the dir */ - return; - } - - if (view->details->update_status_idle_id == 0) { - view->details->update_status_idle_id = - g_idle_add_full (G_PRIORITY_DEFAULT_IDLE - 20, - update_status_idle_callback, view, NULL); - } -} - -/** - * nautilus_view_notify_selection_changed: - * - * Notify this view that the selection has changed. This is normally - * called only by subclasses. - * @view: NautilusView whose selection has changed. - * - **/ -void -nautilus_view_notify_selection_changed (NautilusView *view) -{ - GtkWindow *window; - GList *selection; - - g_return_if_fail (NAUTILUS_IS_VIEW (view)); - - selection = nautilus_view_get_selection (view); - window = nautilus_view_get_containing_window (view); - DEBUG_FILES (selection, "Selection changed in window %p", window); - nautilus_file_list_free (selection); - - view->details->selection_was_removed = FALSE; - - /* Schedule a display of the new selection. */ - if (view->details->display_selection_idle_id == 0) { - view->details->display_selection_idle_id - = g_idle_add (display_selection_info_idle_callback, - view); - } - - if (view->details->batching_selection_level != 0) { - view->details->selection_changed_while_batched = TRUE; - } else { - /* Here is the work we do only when we're not - * batching selection changes. In other words, it's the slower - * stuff that we don't want to slow down selection techniques - * such as rubberband-selecting in icon view. - */ - - /* Schedule an update of menu item states to match selection */ - schedule_update_context_menus (view); - } -} - -static void -file_changed_callback (NautilusFile *file, gpointer callback_data) -{ - NautilusView *view = NAUTILUS_VIEW (callback_data); - - schedule_changes (view); - - schedule_update_context_menus (view); - schedule_update_status (view); -} - -/** - * load_directory: - * - * Switch the displayed location to a new uri. If the uri is not valid, - * the location will not be switched; user feedback will be provided instead. - * @view: NautilusView whose location will be changed. - * @uri: A string representing the uri to switch to. - * - **/ -static void -load_directory (NautilusView *view, - NautilusDirectory *directory) -{ - NautilusDirectory *old_directory; - NautilusFile *old_file; - NautilusFileAttributes attributes; - - g_assert (NAUTILUS_IS_VIEW (view)); - g_assert (NAUTILUS_IS_DIRECTORY (directory)); - - nautilus_profile_start (NULL); - - nautilus_view_stop_loading (view); - g_signal_emit (view, signals[CLEAR], 0); - - view->details->loading = TRUE; - - setup_loading_floating_bar (view); - - /* Update menus when directory is empty, before going to new - * location, so they won't have any false lingering knowledge - * of old selection. - */ - schedule_update_context_menus (view); - - while (view->details->subdirectory_list != NULL) { - nautilus_view_remove_subdirectory (view, - view->details->subdirectory_list->data); - } - - old_directory = view->details->model; - - nautilus_directory_ref (directory); - view->details->model = directory; - nautilus_directory_unref (old_directory); - - old_file = view->details->directory_as_file; - view->details->directory_as_file = - nautilus_directory_get_corresponding_file (directory); - nautilus_file_unref (old_file); - - /* FIXME bugzilla.gnome.org 45062: In theory, we also need to monitor metadata here (as - * well as doing a call when ready), in case external forces - * change the directory's file metadata. - */ - attributes = - NAUTILUS_FILE_ATTRIBUTE_INFO | - NAUTILUS_FILE_ATTRIBUTE_MOUNT | - NAUTILUS_FILE_ATTRIBUTE_FILESYSTEM_INFO; - view->details->metadata_for_directory_as_file_pending = TRUE; - view->details->metadata_for_files_in_directory_pending = TRUE; - nautilus_file_call_when_ready - (view->details->directory_as_file, - attributes, - metadata_for_directory_as_file_ready_callback, view); - nautilus_directory_call_when_ready - (view->details->model, - attributes, - FALSE, - metadata_for_files_in_directory_ready_callback, view); - - /* If capabilities change, then we need to update the menus - * because of New Folder, and relative emblems. - */ - attributes = - NAUTILUS_FILE_ATTRIBUTE_INFO | - NAUTILUS_FILE_ATTRIBUTE_FILESYSTEM_INFO; - nautilus_file_monitor_add (view->details->directory_as_file, - &view->details->directory_as_file, - attributes); - - view->details->file_changed_handler_id = g_signal_connect - (view->details->directory_as_file, "changed", - G_CALLBACK (file_changed_callback), view); - - nautilus_profile_end (NULL); -} - -static void -finish_loading (NautilusView *view) -{ - NautilusFileAttributes attributes; - - nautilus_profile_start (NULL); - - /* Tell interested parties that we've begun loading this directory now. - * Subclasses use this to know that the new metadata is now available. - */ - nautilus_profile_start ("BEGIN_LOADING"); - g_signal_emit (view, signals[BEGIN_LOADING], 0); - nautilus_profile_end ("BEGIN_LOADING"); - - check_empty_states (view); - - if (nautilus_directory_are_all_files_seen (view->details->model)) { - /* Unschedule a pending update and schedule a new one with the minimal - * update interval. This gives the view a short chance at gathering the - * (cached) deep counts. - */ - unschedule_display_of_pending_files (view); - schedule_timeout_display_of_pending_files (view, UPDATE_INTERVAL_MIN); - } - - /* Start loading. */ - - /* Connect handlers to learn about loading progress. */ - view->details->done_loading_handler_id = g_signal_connect - (view->details->model, "done-loading", - G_CALLBACK (done_loading_callback), view); - view->details->load_error_handler_id = g_signal_connect - (view->details->model, "load-error", - G_CALLBACK (load_error_callback), view); - - /* Monitor the things needed to get the right icon. Also - * monitor a directory's item count because the "size" - * attribute is based on that, and the file's metadata - * and possible custom name. - */ - attributes = - NAUTILUS_FILE_ATTRIBUTES_FOR_ICON | - NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT | - NAUTILUS_FILE_ATTRIBUTE_INFO | - NAUTILUS_FILE_ATTRIBUTE_LINK_INFO | - NAUTILUS_FILE_ATTRIBUTE_MOUNT | - NAUTILUS_FILE_ATTRIBUTE_EXTENSION_INFO; - - nautilus_directory_file_monitor_add (view->details->model, - &view->details->model, - view->details->show_hidden_files, - attributes, - files_added_callback, view); - - view->details->files_added_handler_id = g_signal_connect - (view->details->model, "files-added", - G_CALLBACK (files_added_callback), view); - view->details->files_changed_handler_id = g_signal_connect - (view->details->model, "files-changed", - G_CALLBACK (files_changed_callback), view); - - nautilus_profile_end (NULL); -} - -static void -finish_loading_if_all_metadata_loaded (NautilusView *view) -{ - if (!view->details->metadata_for_directory_as_file_pending && - !view->details->metadata_for_files_in_directory_pending) { - finish_loading (view); - } -} - -static void -metadata_for_directory_as_file_ready_callback (NautilusFile *file, - gpointer callback_data) -{ - NautilusView *view; - - view = callback_data; - - g_assert (NAUTILUS_IS_VIEW (view)); - g_assert (view->details->directory_as_file == file); - g_assert (view->details->metadata_for_directory_as_file_pending); - - nautilus_profile_start (NULL); - - view->details->metadata_for_directory_as_file_pending = FALSE; - - finish_loading_if_all_metadata_loaded (view); - nautilus_profile_end (NULL); -} - -static void -metadata_for_files_in_directory_ready_callback (NautilusDirectory *directory, - GList *files, - gpointer callback_data) -{ - NautilusView *view; - - view = callback_data; - - g_assert (NAUTILUS_IS_VIEW (view)); - g_assert (view->details->model == directory); - g_assert (view->details->metadata_for_files_in_directory_pending); - - nautilus_profile_start (NULL); - - view->details->metadata_for_files_in_directory_pending = FALSE; - - finish_loading_if_all_metadata_loaded (view); - nautilus_profile_end (NULL); -} - -static void -disconnect_handler (GObject *object, guint *id) -{ - if (*id != 0) { - g_signal_handler_disconnect (object, *id); - *id = 0; - } -} - -static void -disconnect_directory_handler (NautilusView *view, guint *id) -{ - disconnect_handler (G_OBJECT (view->details->model), id); -} - -static void -disconnect_directory_as_file_handler (NautilusView *view, guint *id) -{ - disconnect_handler (G_OBJECT (view->details->directory_as_file), id); -} - -static void -disconnect_model_handlers (NautilusView *view) -{ - if (view->details->model == NULL) { - return; - } - disconnect_directory_handler (view, &view->details->files_added_handler_id); - disconnect_directory_handler (view, &view->details->files_changed_handler_id); - disconnect_directory_handler (view, &view->details->done_loading_handler_id); - disconnect_directory_handler (view, &view->details->load_error_handler_id); - disconnect_directory_as_file_handler (view, &view->details->file_changed_handler_id); - nautilus_file_cancel_call_when_ready (view->details->directory_as_file, - metadata_for_directory_as_file_ready_callback, - view); - nautilus_directory_cancel_callback (view->details->model, - metadata_for_files_in_directory_ready_callback, - view); - nautilus_directory_file_monitor_remove (view->details->model, - &view->details->model); - nautilus_file_monitor_remove (view->details->directory_as_file, - &view->details->directory_as_file); -} - -static void -nautilus_view_select_file (NautilusView *view, NautilusFile *file) -{ - GList file_list; - - file_list.data = file; - file_list.next = NULL; - file_list.prev = NULL; - nautilus_view_call_set_selection (view, &file_list); -} - -static gboolean -remove_all (gpointer key, gpointer value, gpointer callback_data) -{ - return TRUE; -} - -/** - * nautilus_view_stop_loading: - * - * Stop the current ongoing process, such as switching to a new uri. - * @view: NautilusView in question. - * - **/ -void -nautilus_view_stop_loading (NautilusView *view) -{ - g_return_if_fail (NAUTILUS_IS_VIEW (view)); - - disconnect_model_handlers (view); - if (view->details->model) { - nautilus_directory_unref (view->details->model); - view->details->model = NULL; - } - unschedule_display_of_pending_files (view); - reset_update_interval (view); - - /* Free extra undisplayed files */ - file_and_directory_list_free (view->details->new_added_files); - view->details->new_added_files = NULL; - - file_and_directory_list_free (view->details->new_changed_files); - view->details->new_changed_files = NULL; - - g_hash_table_foreach_remove (view->details->non_ready_files, remove_all, NULL); - - file_and_directory_list_free (view->details->old_added_files); - view->details->old_added_files = NULL; - - file_and_directory_list_free (view->details->old_changed_files); - view->details->old_changed_files = NULL; - - g_list_free_full (view->details->pending_selection, g_object_unref); - view->details->pending_selection = NULL; - - done_loading (view, FALSE); -} - -gboolean -nautilus_view_is_editable (NautilusView *view) -{ - NautilusDirectory *directory; - - directory = nautilus_view_get_model (view); - - if (directory != NULL) { - return nautilus_directory_is_editable (directory); - } - - return TRUE; -} - -static gboolean -real_is_read_only (NautilusView *view) -{ - NautilusFile *file; - - if (!nautilus_view_is_editable (view)) { - return TRUE; - } - - file = nautilus_view_get_directory_as_file (view); - if (file != NULL) { - return !nautilus_file_can_write (file); - } - return FALSE; -} - -/** - * nautilus_view_should_show_file - * - * Returns whether or not this file should be displayed based on - * current filtering options. - */ -gboolean -nautilus_view_should_show_file (NautilusView *view, NautilusFile *file) -{ - return nautilus_file_should_show (file, - view->details->show_hidden_files, - view->details->show_foreign_files); -} - -static gboolean -real_using_manual_layout (NautilusView *view) -{ - g_return_val_if_fail (NAUTILUS_IS_VIEW (view), FALSE); - - return FALSE; -} - -void -nautilus_view_ignore_hidden_file_preferences (NautilusView *view) -{ - g_return_if_fail (view->details->model == NULL); - - if (view->details->ignore_hidden_file_preferences) { - return; - } - - view->details->show_hidden_files = FALSE; - view->details->ignore_hidden_file_preferences = TRUE; -} - -void -nautilus_view_set_show_foreign (NautilusView *view, - gboolean show_foreign) -{ - view->details->show_foreign_files = show_foreign; -} - -char * -nautilus_view_get_uri (NautilusView *view) -{ - g_return_val_if_fail (NAUTILUS_IS_VIEW (view), NULL); - if (view->details->model == NULL) { - return NULL; - } - return nautilus_directory_get_uri (view->details->model); -} - -void -nautilus_view_move_copy_items (NautilusView *view, - const GList *item_uris, - GArray *relative_item_points, - const char *target_uri, - int copy_action, - int x, int y) -{ - NautilusFile *target_file; - - g_assert (relative_item_points == NULL - || relative_item_points->len == 0 - || g_list_length ((GList *)item_uris) == relative_item_points->len); - - /* add the drop location to the icon offsets */ - offset_drop_points (relative_item_points, x, y); - - target_file = nautilus_file_get_existing_by_uri (target_uri); - /* special-case "command:" here instead of starting a move/copy */ - if (target_file != NULL && nautilus_file_is_launcher (target_file)) { - nautilus_file_unref (target_file); - nautilus_launch_desktop_file ( - gtk_widget_get_screen (GTK_WIDGET (view)), - target_uri, item_uris, - nautilus_view_get_containing_window (view)); - return; - } else if (copy_action == GDK_ACTION_COPY && - nautilus_is_file_roller_installed () && - target_file != NULL && - nautilus_file_is_archive (target_file)) { - char *command, *quoted_uri, *tmp; - const GList *l; - GdkScreen *screen; - - /* Handle dropping onto a file-roller archiver file, instead of starting a move/copy */ - - nautilus_file_unref (target_file); - - quoted_uri = g_shell_quote (target_uri); - command = g_strconcat ("file-roller -a ", quoted_uri, NULL); - g_free (quoted_uri); - - for (l = item_uris; l != NULL; l = l->next) { - quoted_uri = g_shell_quote ((char *) l->data); - - tmp = g_strconcat (command, " ", quoted_uri, NULL); - g_free (command); - command = tmp; - - g_free (quoted_uri); - } - - screen = gtk_widget_get_screen (GTK_WIDGET (view)); - if (screen == NULL) { - screen = gdk_screen_get_default (); - } - - nautilus_launch_application_from_command (screen, command, FALSE, NULL); - g_free (command); - - return; - } - nautilus_file_unref (target_file); - - nautilus_file_operations_copy_move - (item_uris, relative_item_points, - target_uri, copy_action, GTK_WIDGET (view), - copy_move_done_callback, pre_copy_move (view)); -} - -static void -nautilus_view_trash_state_changed_callback (NautilusTrashMonitor *trash_monitor, - gboolean state, gpointer callback_data) -{ - NautilusView *view; - - view = (NautilusView *) callback_data; - g_assert (NAUTILUS_IS_VIEW (view)); - - schedule_update_context_menus (view); -} - -void -nautilus_view_start_batching_selection_changes (NautilusView *view) -{ - g_return_if_fail (NAUTILUS_IS_VIEW (view)); - - ++view->details->batching_selection_level; - view->details->selection_changed_while_batched = FALSE; -} - -void -nautilus_view_stop_batching_selection_changes (NautilusView *view) -{ - g_return_if_fail (NAUTILUS_IS_VIEW (view)); - g_return_if_fail (view->details->batching_selection_level > 0); - - if (--view->details->batching_selection_level == 0) { - if (view->details->selection_changed_while_batched) { - nautilus_view_notify_selection_changed (view); - } - } -} - -static GArray * -real_get_selected_icon_locations (NautilusView *view) -{ - /* By default, just return an empty list. */ - return g_array_new (FALSE, TRUE, sizeof (GdkPoint)); -} - -static void -nautilus_view_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - NautilusView *view = NAUTILUS_VIEW (object); - - switch (prop_id) { - case PROP_ICON: - g_value_set_object (value, nautilus_view_get_icon (view)); - break; - - case PROP_VIEW_WIDGET: - g_value_set_object (value, nautilus_view_get_view_widget (view)); - break; - - default: - g_assert_not_reached (); - - } -} - -static void -nautilus_view_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - NautilusView *directory_view; - NautilusWindowSlot *slot; - - directory_view = NAUTILUS_VIEW (object); - - switch (prop_id) { - case PROP_WINDOW_SLOT: - g_assert (directory_view->details->slot == NULL); - - slot = NAUTILUS_WINDOW_SLOT (g_value_get_object (value)); - directory_view->details->slot = slot; - - g_signal_connect_object (directory_view->details->slot, - "active", G_CALLBACK (slot_active), - directory_view, 0); - g_signal_connect_object (directory_view->details->slot, - "inactive", G_CALLBACK (slot_inactive), - directory_view, 0); - break; - case PROP_SUPPORTS_ZOOMING: - directory_view->details->supports_zooming = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - - -gboolean -nautilus_view_handle_scroll_event (NautilusView *directory_view, - GdkEventScroll *event) -{ - static gdouble total_delta_y = 0; - gdouble delta_x, delta_y; - - if (event->state & GDK_CONTROL_MASK) { - switch (event->direction) { - case GDK_SCROLL_UP: - /* Zoom In */ - nautilus_view_bump_zoom_level (directory_view, 1); - return TRUE; - - case GDK_SCROLL_DOWN: - /* Zoom Out */ - nautilus_view_bump_zoom_level (directory_view, -1); - return TRUE; - - case GDK_SCROLL_SMOOTH: - gdk_event_get_scroll_deltas ((const GdkEvent *) event, - &delta_x, &delta_y); - - /* try to emulate a normal scrolling event by summing deltas */ - total_delta_y += delta_y; - - if (total_delta_y >= 1) { - total_delta_y = 0; - /* emulate scroll down */ - nautilus_view_bump_zoom_level (directory_view, -1); - return TRUE; - } else if (total_delta_y <= - 1) { - total_delta_y = 0; - /* emulate scroll up */ - nautilus_view_bump_zoom_level (directory_view, 1); - return TRUE; - } else { - /* eat event */ - return TRUE; - } - - case GDK_SCROLL_LEFT: - case GDK_SCROLL_RIGHT: - break; - - default: - g_assert_not_reached (); - } - } - - return FALSE; -} - -/* handle Shift+Scroll, which will cause a zoom-in/out */ -static gboolean -nautilus_view_scroll_event (GtkWidget *widget, - GdkEventScroll *event) -{ - NautilusView *directory_view; - - directory_view = NAUTILUS_VIEW (widget); - if (nautilus_view_handle_scroll_event (directory_view, event)) { - return TRUE; - } - - return FALSE; -} - - -static void -action_reload_enabled_changed (GActionGroup *action_group, - gchar *action_name, - gboolean enabled, - NautilusView *view) -{ - gtk_widget_set_visible (view->details->reload, enabled); -} - -static void -action_stop_enabled_changed (GActionGroup *action_group, - gchar *action_name, - gboolean enabled, - NautilusView *view) -{ - gtk_widget_set_visible (view->details->stop, enabled); -} - -static void -nautilus_view_parent_set (GtkWidget *widget, - GtkWidget *old_parent) -{ - NautilusWindow *window; - NautilusView *view; - GtkWidget *parent; - - view = NAUTILUS_VIEW (widget); - - parent = gtk_widget_get_parent (widget); - window = nautilus_view_get_window (view); - g_assert (parent == NULL || old_parent == NULL); - - if (GTK_WIDGET_CLASS (nautilus_view_parent_class)->parent_set != NULL) { - GTK_WIDGET_CLASS (nautilus_view_parent_class)->parent_set (widget, old_parent); - } - - if (view->details->stop_signal_handler > 0) { - g_signal_handler_disconnect (window, view->details->stop_signal_handler); - view->details->stop_signal_handler = 0; - } - - if (view->details->reload_signal_handler > 0) { - g_signal_handler_disconnect (window, view->details->reload_signal_handler); - view->details->reload_signal_handler = 0; - } - - if (parent != NULL) { - g_assert (old_parent == NULL); - - if (view->details->slot == nautilus_window_get_active_slot (window)) { - view->details->active = TRUE; - gtk_widget_insert_action_group (GTK_WIDGET (nautilus_view_get_window (view)), - "view", - G_ACTION_GROUP (view->details->view_action_group)); - } - - view->details->stop_signal_handler = - g_signal_connect (window, - "action-enabled-changed::stop", - G_CALLBACK (action_stop_enabled_changed), - view); - view->details->reload_signal_handler = - g_signal_connect (window, - "action-enabled-changed::reload", - G_CALLBACK (action_reload_enabled_changed), - view); - } else { - remove_update_context_menus_timeout_callback (view); - gtk_widget_insert_action_group (GTK_WIDGET (nautilus_view_get_window (view)), - "view", - NULL); - } -} - -static gboolean -nautilus_view_key_press_event (GtkWidget *widget, - GdkEventKey *event) -{ - NautilusView *view; - gint i; - - view = NAUTILUS_VIEW (widget); - - for (i = 0; i < G_N_ELEMENTS (extra_view_keybindings); i++) { - if (extra_view_keybindings[i].keyval == event->keyval) { - GAction *action; - - action = g_action_map_lookup_action (G_ACTION_MAP (view->details->view_action_group), - extra_view_keybindings[i].action); - - if (g_action_get_enabled (action)) { - g_action_activate (action, NULL); - return GDK_EVENT_STOP; - } - - break; - } - } - - return GDK_EVENT_PROPAGATE; -} - -static void -nautilus_view_class_init (NautilusViewClass *klass) -{ - GObjectClass *oclass; - GtkWidgetClass *widget_class; - - widget_class = GTK_WIDGET_CLASS (klass); - oclass = G_OBJECT_CLASS (klass); - - oclass->finalize = nautilus_view_finalize; - oclass->get_property = nautilus_view_get_property; - oclass->set_property = nautilus_view_set_property; - - widget_class->destroy = nautilus_view_destroy; - widget_class->key_press_event = nautilus_view_key_press_event; - widget_class->scroll_event = nautilus_view_scroll_event; - widget_class->parent_set = nautilus_view_parent_set; - widget_class->grab_focus = nautilus_view_grab_focus; - - g_type_class_add_private (klass, sizeof (NautilusViewDetails)); - - signals[ADD_FILE] = - g_signal_new ("add-file", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NautilusViewClass, add_file), - NULL, NULL, - g_cclosure_marshal_generic, - G_TYPE_NONE, 2, NAUTILUS_TYPE_FILE, NAUTILUS_TYPE_DIRECTORY); - signals[BEGIN_FILE_CHANGES] = - g_signal_new ("begin-file-changes", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NautilusViewClass, begin_file_changes), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - signals[BEGIN_LOADING] = - g_signal_new ("begin-loading", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NautilusViewClass, begin_loading), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - signals[CLEAR] = - g_signal_new ("clear", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NautilusViewClass, clear), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - signals[END_FILE_CHANGES] = - g_signal_new ("end-file-changes", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NautilusViewClass, end_file_changes), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - signals[END_LOADING] = - g_signal_new ("end-loading", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NautilusViewClass, end_loading), - NULL, NULL, - g_cclosure_marshal_VOID__BOOLEAN, - G_TYPE_NONE, 1, G_TYPE_BOOLEAN); - signals[FILE_CHANGED] = - g_signal_new ("file-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NautilusViewClass, file_changed), - NULL, NULL, - g_cclosure_marshal_generic, - G_TYPE_NONE, 2, NAUTILUS_TYPE_FILE, NAUTILUS_TYPE_DIRECTORY); - signals[REMOVE_FILE] = - g_signal_new ("remove-file", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NautilusViewClass, remove_file), - NULL, NULL, - g_cclosure_marshal_generic, - G_TYPE_NONE, 2, NAUTILUS_TYPE_FILE, NAUTILUS_TYPE_DIRECTORY); - signals[SELECTION_CHANGED] = - g_signal_new ("selection-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - klass->get_selected_icon_locations = real_get_selected_icon_locations; - klass->is_read_only = real_is_read_only; - klass->can_rename_file = can_rename_file; - klass->get_backing_uri = real_get_backing_uri; - klass->using_manual_layout = real_using_manual_layout; - klass->get_window = nautilus_view_get_window; - klass->update_context_menus = real_update_context_menus; - klass->update_actions_state = real_update_actions_state; - - copied_files_atom = gdk_atom_intern ("x-special/gnome-copied-files", FALSE); - - properties[PROP_WINDOW_SLOT] = - g_param_spec_object ("window-slot", - "Window Slot", - "The parent window slot reference", - NAUTILUS_TYPE_WINDOW_SLOT, - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY); - properties[PROP_SUPPORTS_ZOOMING] = - g_param_spec_boolean ("supports-zooming", - "Supports zooming", - "Whether the view supports zooming", - TRUE, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - properties[PROP_ICON] = - g_param_spec_object ("icon", - "Icon", - "The icon that represents the view", - G_TYPE_ICON, - G_PARAM_READABLE); - - properties[PROP_VIEW_WIDGET] = - g_param_spec_object ("view-widget", - "View widget", - "The view's widget that will appear under the view menu button", - GTK_TYPE_WIDGET, - G_PARAM_READABLE); - - g_object_class_install_properties (oclass, NUM_PROPERTIES, properties); -} - -static void -nautilus_view_init (NautilusView *view) -{ - GtkBuilder *builder; - AtkObject *atk_object; - NautilusDirectory *scripts_directory; - NautilusDirectory *templates_directory; - gchar *templates_uri; - GApplication *app; - const gchar *open_accels[] = { - "<control>o", - "<alt>Down", - NULL - }; - - nautilus_profile_start (NULL); - - view->details = G_TYPE_INSTANCE_GET_PRIVATE (view, NAUTILUS_TYPE_VIEW, - NautilusViewDetails); - - /* NautilusFloatingBar listen to its parent's 'enter-notify-event' signal - * and GtkOverlay doesn't have it enabled by default, so we have to add them - * here. - */ - gtk_widget_add_events (GTK_WIDGET (view), - GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); - - /* View menu */ - builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/nautilus-toolbar-view-menu.xml"); - view->details->view_menu_widget = g_object_ref (gtk_builder_get_object (builder, "view_menu_widget")); - view->details->zoom_level_scale = GTK_WIDGET (gtk_builder_get_object (builder, "zoom_level_scale")); - view->details->zoom_adjustment = GTK_ADJUSTMENT (gtk_builder_get_object (builder, "zoom_adjustment")); - - view->details->sort_menu = GTK_WIDGET (gtk_builder_get_object (builder, "sort_menu")); - view->details->sort_trash_time = GTK_WIDGET (gtk_builder_get_object (builder, "sort_trash_time")); - view->details->sort_search_relevance = GTK_WIDGET (gtk_builder_get_object (builder, "sort_search_relevance")); - view->details->visible_columns = GTK_WIDGET (gtk_builder_get_object (builder, "visible_columns")); - view->details->reload = GTK_WIDGET (gtk_builder_get_object (builder, "reload")); - view->details->stop = GTK_WIDGET (gtk_builder_get_object (builder, "stop")); - - g_signal_connect (view->details->zoom_level_scale, "value-changed", - G_CALLBACK (zoom_level_changed), view); - - g_object_unref (builder); - - /* Scrolled Window */ - view->details->scrolled_window = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (view->details->scrolled_window), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - gtk_widget_show (view->details->scrolled_window); - - g_signal_connect_swapped (view->details->scrolled_window, - "scroll-event", - G_CALLBACK (nautilus_view_scroll_event), - view); - - gtk_container_add (GTK_CONTAINER (view), view->details->scrolled_window); - - /* Empty states */ - builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/nautilus-no-search-results.ui"); - view->details->no_search_results_widget = GTK_WIDGET (gtk_builder_get_object (builder, "no_search_results")); - gtk_overlay_add_overlay (GTK_OVERLAY (view), view->details->no_search_results_widget); - g_object_unref (builder); - - builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/nautilus-folder-is-empty.ui"); - view->details->folder_is_empty_widget = GTK_WIDGET (gtk_builder_get_object (builder, "folder_is_empty")); - gtk_overlay_add_overlay (GTK_OVERLAY (view), view->details->folder_is_empty_widget); - g_object_unref (builder); - - /* Floating bar */ - view->details->floating_bar = nautilus_floating_bar_new (NULL, NULL, FALSE); - gtk_widget_set_halign (view->details->floating_bar, GTK_ALIGN_END); - gtk_widget_set_valign (view->details->floating_bar, GTK_ALIGN_END); - gtk_overlay_add_overlay (GTK_OVERLAY (view), view->details->floating_bar); - - g_signal_connect (view->details->floating_bar, - "action", - G_CALLBACK (floating_bar_action_cb), - view); - - /* 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_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)); - - 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); - - /* 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.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 */ - gtk_application_set_accels_for_action (GTK_APPLICATION (app), - "view.open-with-default-application", open_accels); - 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", "Delete"); - nautilus_application_add_accelerator (app, "view.delete-from-trash", "Delete"); - nautilus_application_add_accelerator (app, "view.delete-permanently-shortcut", "<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.new-folder", "<control><shift>n"); - /* 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"); - - /* Show a warning dialog to inform the user that the shorcut for move to trash - * changed */ - nautilus_application_add_accelerator (app, "view.show-move-to-trash-shortcut-changed-dialog", "<control>Delete"); - - nautilus_profile_end (NULL); -} - -NautilusView * -nautilus_view_new (const gchar *id, - NautilusWindowSlot *slot) -{ - NautilusView *view = NULL; - - if (g_strcmp0 (id, NAUTILUS_CANVAS_VIEW_ID) == 0) { - view = nautilus_canvas_view_new (slot); - } else if (g_strcmp0 (id, NAUTILUS_LIST_VIEW_ID) == 0) { - view = nautilus_list_view_new (slot); - } else if (g_strcmp0 (id, NAUTILUS_DESKTOP_CANVAS_VIEW_ID) == 0) { - view = nautilus_desktop_canvas_view_new (slot); - } -#if ENABLE_EMPTY_VIEW - else if (g_strcmp0 (id, NAUTILUS_EMPTY_VIEW_ID) == 0) { - view = nautilus_empty_view_new (slot); - } -#endif - - if (view == NULL) { - g_critical ("Unknown view type ID: %s", id); - } else if (g_object_is_floating (view)) { - g_object_ref_sink (view); - } - - return view; -} diff --git a/src/nautilus-view.h b/src/nautilus-view.h deleted file mode 100644 index 263eec97e..000000000 --- a/src/nautilus-view.h +++ /dev/null @@ -1,401 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* nautilus-view.h - * - * Copyright (C) 1999, 2000 Free Software Foundaton - * Copyright (C) 2000, 2001 Eazel, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, see <http://www.gnu.org/licenses/>. - * - * Authors: Ettore Perazzoli - * Darin Adler <darin@bentspoon.com> - * John Sullivan <sullivan@eazel.com> - * Pavel Cisler <pavel@eazel.com> - */ - -#ifndef NAUTILUS_VIEW_H -#define NAUTILUS_VIEW_H - -#include <gtk/gtk.h> -#include <gio/gio.h> - -#include <libnautilus-private/nautilus-directory.h> -#include <libnautilus-private/nautilus-file.h> -#include <libnautilus-private/nautilus-link.h> - -typedef struct NautilusView NautilusView; -typedef struct NautilusViewClass NautilusViewClass; - -#include "nautilus-window.h" -#include "nautilus-window-slot.h" - -#if ENABLE_EMPTY_VIEW -#define NAUTILUS_EMPTY_VIEW_ID "OAFIID:Nautilus_File_Manager_Empty_View" -#endif - -#define NAUTILUS_CANVAS_VIEW_ID "OAFIID:Nautilus_File_Manager_Canvas_View" -#define NAUTILUS_DESKTOP_CANVAS_VIEW_ID "OAFIID:Nautilus_File_Manager_Desktop_Canvas_View" -#define NAUTILUS_LIST_VIEW_ID "OAFIID:Nautilus_File_Manager_List_View" - -#define NAUTILUS_TYPE_VIEW nautilus_view_get_type() -#define NAUTILUS_VIEW(obj)\ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_VIEW, NautilusView)) -#define NAUTILUS_VIEW_CLASS(klass)\ - (G_TYPE_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_VIEW, NautilusViewClass)) -#define NAUTILUS_IS_VIEW(obj)\ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NAUTILUS_TYPE_VIEW)) -#define NAUTILUS_IS_VIEW_CLASS(klass)\ - (G_TYPE_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_VIEW)) -#define NAUTILUS_VIEW_GET_CLASS(obj)\ - (G_TYPE_INSTANCE_GET_CLASS ((obj), NAUTILUS_TYPE_VIEW, NautilusViewClass)) - -typedef struct NautilusViewDetails NautilusViewDetails; - -struct NautilusView { - GtkOverlay parent; - - NautilusViewDetails *details; -}; - -struct NautilusViewClass { - GtkOverlayClass parent_class; - - /* The 'clear' signal is emitted to empty the view of its contents. - * It must be replaced by each subclass. - */ - void (* clear) (NautilusView *view); - - /* The 'begin_file_changes' signal is emitted before a set of files - * are added to the view. It can be replaced by a subclass to do any - * necessary preparation for a set of new files. The default - * implementation does nothing. - */ - void (* begin_file_changes) (NautilusView *view); - - /* The 'add_file' signal is emitted to add one file to the view. - * It must be replaced by each subclass. - */ - void (* add_file) (NautilusView *view, - NautilusFile *file, - NautilusDirectory *directory); - void (* remove_file) (NautilusView *view, - NautilusFile *file, - NautilusDirectory *directory); - - /* The 'file_changed' signal is emitted to signal a change in a file, - * including the file being removed. - * It must be replaced by each subclass. - */ - void (* file_changed) (NautilusView *view, - NautilusFile *file, - NautilusDirectory *directory); - - /* The 'end_file_changes' signal is emitted after a set of files - * are added to the view. It can be replaced by a subclass to do any - * necessary cleanup (typically, cleanup for code in begin_file_changes). - * The default implementation does nothing. - */ - void (* end_file_changes) (NautilusView *view); - - /* The 'begin_loading' signal is emitted before any of the contents - * of a directory are added to the view. It can be replaced by a - * subclass to do any necessary preparation to start dealing with a - * new directory. The default implementation does nothing. - */ - void (* begin_loading) (NautilusView *view); - - /* The 'end_loading' signal is emitted after all of the contents - * of a directory are added to the view. It can be replaced by a - * subclass to do any necessary clean-up. The default implementation - * does nothing. - * - * If all_files_seen is true, the handler may assume that - * no load error ocurred, and all files of the underlying - * directory were loaded. - * - * Otherwise, end_loading was emitted due to cancellation, - * which usually means that not all files are available. - */ - void (* end_loading) (NautilusView *view, - gboolean all_files_seen); - - /* Function pointers that don't have corresponding signals */ - - /* get_backing uri is a function pointer for subclasses to - * override. Subclasses may replace it with a function that - * returns the URI for the location where to create new folders, - * files, links and paste the clipboard to. - */ - - char * (* get_backing_uri) (NautilusView *view); - - /* get_selection is not a signal; it is just a function pointer for - * subclasses to replace (override). Subclasses must replace it - * with a function that returns a newly-allocated GList of - * NautilusFile pointers. - */ - GList * (* get_selection) (NautilusView *view); - - /* get_selection_for_file_transfer is a function pointer for - * subclasses to replace (override). Subclasses must replace it - * with a function that returns a newly-allocated GList of - * NautilusFile pointers. The difference from get_selection is - * that any files in the selection that also has a parent folder - * in the selection is not included. - */ - GList * (* get_selection_for_file_transfer)(NautilusView *view); - - /* select_all is a function pointer that subclasses must override to - * select all of the items in the view */ - void (* select_all) (NautilusView *view); - - /* select_first is a function pointer that subclasses must override to - * select the first item in the view */ - void (* select_first) (NautilusView *view); - - /* set_selection is a function pointer that subclasses must - * override to select the specified items (and unselect all - * others). The argument is a list of NautilusFiles. */ - - void (* set_selection) (NautilusView *view, - GList *selection); - - /* invert_selection is a function pointer that subclasses must - * override to invert selection. */ - - void (* invert_selection) (NautilusView *view); - - /* Return an array of locations of selected icons in their view. */ - GArray * (* get_selected_icon_locations) (NautilusView *view); - - /* bump_zoom_level is a function pointer that subclasses must override - * to change the zoom level of an object. */ - void (* bump_zoom_level) (NautilusView *view, - int zoom_increment); - - /* restore_default_zoom_level is a function pointer that subclasses must override - * to restore the zoom level of an object to a default setting. */ - void (* restore_default_zoom_level) (NautilusView *view); - - /* can_zoom_in is a function pointer that subclasses must override to - * return whether the view is at maximum size (furthest-in zoom level) */ - gboolean (* can_zoom_in) (NautilusView *view); - - /* can_zoom_out is a function pointer that subclasses must override to - * return whether the view is at minimum size (furthest-out zoom level) */ - gboolean (* can_zoom_out) (NautilusView *view); - - /* reveal_selection is a function pointer that subclasses may - * override to make sure the selected items are sufficiently - * apparent to the user (e.g., scrolled into view). By default, - * this does nothing. - */ - void (* reveal_selection) (NautilusView *view); - - /* merge_menus is a function pointer that subclasses can override to - * add their own menu items to the window's menu bar. - * If overridden, subclasses must call parent class's function. - */ - void (* merge_menus) (NautilusView *view); - void (* unmerge_menus) (NautilusView *view); - - /* update_menus is a function pointer that subclasses can override to - * update the sensitivity or wording of menu items in the menu bar. - * It is called (at least) whenever the selection changes. If overridden, - * subclasses must call parent class's function. - */ - void (* update_context_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 - * presented when only a partial list is provided. - */ - int (* compare_files) (NautilusView *view, - NautilusFile *a, - NautilusFile *b); - - /* using_manual_layout is a function pointer that subclasses may - * override to control whether or not items can be freely positioned - * on the user-visible area. - * Note that this value is not guaranteed to be constant within the - * view's lifecycle. */ - gboolean (* using_manual_layout) (NautilusView *view); - - /* is_read_only is a function pointer that subclasses may - * override to control whether or not the user is allowed to - * change the contents of the currently viewed directory. The - * default implementation checks the permissions of the - * directory. - */ - gboolean (* is_read_only) (NautilusView *view); - - /* is_empty is a function pointer that subclasses must - * override to report whether the view contains any items. - */ - gboolean (* is_empty) (NautilusView *view); - - gboolean (* can_rename_file) (NautilusView *view, - NautilusFile *file); - - /* convert *point from widget's coordinate system to a coordinate - * system used for specifying file operation positions, which is view-specific. - * - * This is used by the the icon view, which converts the screen position to a zoom - * level-independent coordinate system. - */ - void (* widget_to_file_operation_position) (NautilusView *view, - GdkPoint *position); - - /* Preference change callbacks, overriden by icon and list views. - * Icon and list views respond by synchronizing to the new preference - * values and forcing an update if appropriate. - */ - void (* click_policy_changed) (NautilusView *view); - void (* sort_directories_first_changed) (NautilusView *view); - - /* Get the id string for this view. Its a constant string, not memory managed */ - const char * (* get_view_id) (NautilusView *view); - - /* Return the uri of the first visible file */ - char * (* get_first_visible_file) (NautilusView *view); - /* Scroll the view so that the file specified by the uri is at the top - of the view */ - void (* scroll_to_file) (NautilusView *view, - const char *uri); - - NautilusWindow * (*get_window) (NautilusView *view); - - GdkRectangle * (*compute_rename_popover_relative_to) (NautilusView *view); - - GIcon * (* get_icon) (NautilusView *view); -}; - -/* GObject support */ -GType nautilus_view_get_type (void); - -NautilusView * nautilus_view_new (const gchar *id, - NautilusWindowSlot *slot); - -/* Functions callable from the user interface and elsewhere. */ -NautilusWindowSlot *nautilus_view_get_nautilus_window_slot (NautilusView *view); -char * nautilus_view_get_uri (NautilusView *view); - -void nautilus_view_display_selection_info (NautilusView *view); - -GdkAtom nautilus_view_get_copied_files_atom (NautilusView *view); - -/* Wrappers for signal emitters. These are normally called - * only by NautilusView itself. They have corresponding signals - * that observers might want to connect with. - */ -gboolean nautilus_view_get_loading (NautilusView *view); - -/* Hooks for subclasses to call. These are normally called only by - * NautilusView and its subclasses - */ -void nautilus_view_activate_files (NautilusView *view, - GList *files, - NautilusWindowOpenFlags flags, - gboolean confirm_multiple); -void nautilus_view_preview_files (NautilusView *view, - GList *files, - GArray *locations); -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); -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, - GdkEventButton *event); -void nautilus_view_pop_up_selection_context_menu (NautilusView *view, - GdkEventButton *event); -gboolean nautilus_view_should_show_file (NautilusView *view, - NautilusFile *file); -gboolean nautilus_view_should_sort_directories_first (NautilusView *view); -void nautilus_view_ignore_hidden_file_preferences (NautilusView *view); -void nautilus_view_set_show_foreign (NautilusView *view, - gboolean show_foreign); -gboolean nautilus_view_handle_scroll_event (NautilusView *view, - GdkEventScroll *event); - -void nautilus_view_add_subdirectory (NautilusView *view, - NautilusDirectory*directory); -void nautilus_view_remove_subdirectory (NautilusView *view, - 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); - -/* file operations */ -char * nautilus_view_get_backing_uri (NautilusView *view); -void nautilus_view_move_copy_items (NautilusView *view, - const GList *item_uris, - GArray *relative_item_points, - const char *target_uri, - int copy_action, - int x, - int y); -void nautilus_view_new_file_with_initial_contents (NautilusView *view, - const char *parent_uri, - const char *filename, - const char *initial_contents, - int length, - GdkPoint *pos); - -/* selection handling */ -void nautilus_view_activate_selection (NautilusView *view); -int nautilus_view_get_selection_count (NautilusView *view); -GList * nautilus_view_get_selection (NautilusView *view); -void nautilus_view_set_selection (NautilusView *view, - GList *selection); - - -void nautilus_view_load_location (NautilusView *view, - GFile *location); -void nautilus_view_stop_loading (NautilusView *view); - -char * nautilus_view_get_first_visible_file (NautilusView *view); -void nautilus_view_scroll_to_file (NautilusView *view, - const char *uri); -char * nautilus_view_get_title (NautilusView *view); -gboolean nautilus_view_supports_zooming (NautilusView *view); -void nautilus_view_bump_zoom_level (NautilusView *view, - int zoom_increment); -void nautilus_view_zoom_to_level (NautilusView *view, - gint level); -void nautilus_view_restore_default_zoom_level (NautilusView *view); -gboolean nautilus_view_can_zoom_in (NautilusView *view); -gboolean nautilus_view_can_zoom_out (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); - -void nautilus_view_action_show_hidden_files (NautilusView *view, - gboolean show_hidden); - -GActionGroup * nautilus_view_get_action_group (NautilusView *view); -GtkWidget* nautilus_view_get_content_widget (NautilusView *view); -gboolean nautilus_view_is_search (NautilusView *view); - -GIcon* nautilus_view_get_icon (NautilusView *view); - -GtkWidget* nautilus_view_get_view_widget (NautilusView *view); - -#endif /* NAUTILUS_VIEW_H */ diff --git a/src/nautilus-window-slot-dnd.c b/src/nautilus-window-slot-dnd.c index 548515cda..71386b140 100644 --- a/src/nautilus-window-slot-dnd.c +++ b/src/nautilus-window-slot-dnd.c @@ -26,7 +26,7 @@ #include <config.h> #include "nautilus-notebook.h" -#include "nautilus-view-dnd.h" +#include "nautilus-files-view-dnd.h" #include "nautilus-window-slot-dnd.h" typedef struct { @@ -331,7 +331,7 @@ slot_proxy_handle_drop (GtkWidget *widget, { GtkWidget *window; NautilusWindowSlot *target_slot; - NautilusView *target_view; + NautilusFilesView *target_view; char *target_uri; GList *uri_list; @@ -368,18 +368,18 @@ slot_proxy_handle_drop (GtkWidget *widget, uri_list = nautilus_drag_uri_list_from_selection_list (drag_info->data.selection_list); g_assert (uri_list != NULL); - nautilus_view_drop_proxy_received_uris (target_view, + nautilus_files_view_drop_proxy_received_uris (target_view, uri_list, target_uri, gdk_drag_context_get_selected_action (context)); g_list_free_full (uri_list, g_free); } else if (drag_info->info == NAUTILUS_ICON_DND_URI_LIST) { - nautilus_view_drop_proxy_received_uris (target_view, + nautilus_files_view_drop_proxy_received_uris (target_view, drag_info->data.uri_list, target_uri, gdk_drag_context_get_selected_action (context)); } if (drag_info->info == NAUTILUS_ICON_DND_NETSCAPE_URL) { - nautilus_view_handle_netscape_url_drop (target_view, + nautilus_files_view_handle_netscape_url_drop (target_view, drag_info->data.netscape_url, target_uri, gdk_drag_context_get_selected_action (context), diff --git a/src/nautilus-window-slot.c b/src/nautilus-window-slot.c index 0c5e3934e..9791cfc31 100644 --- a/src/nautilus-window-slot.c +++ b/src/nautilus-window-slot.c @@ -74,8 +74,8 @@ struct NautilusWindowSlotDetails { gchar *title; /* Viewed file */ - NautilusView *content_view; - NautilusView *new_content_view; + NautilusFilesView *content_view; + NautilusFilesView *new_content_view; NautilusFile *viewed_file; gboolean viewed_file_seen; gboolean viewed_file_in_trash; @@ -137,7 +137,7 @@ nautilus_window_slot_sync_search_widgets (NautilusWindowSlot *slot) nautilus_window_slot_set_search_visible (slot, slot->details->search_visible || (slot->details->content_view && - nautilus_view_is_search (slot->details->content_view))); + nautilus_files_view_is_search (slot->details->content_view))); } static gboolean @@ -147,7 +147,7 @@ nautilus_window_slot_content_view_matches_iid (NautilusWindowSlot *slot, if (slot->details->content_view == NULL) { return FALSE; } - return g_strcmp0 (nautilus_view_get_view_id (slot->details->content_view), iid) == 0; + return g_strcmp0 (nautilus_files_view_get_view_id (slot->details->content_view), iid) == 0; } void @@ -244,7 +244,7 @@ query_editor_activated_callback (NautilusQueryEditor *editor, NautilusWindowSlot *slot) { if (slot->details->content_view != NULL) { - nautilus_view_activate_selection (slot->details->content_view); + nautilus_files_view_activate_selection (slot->details->content_view); } } @@ -741,7 +741,7 @@ nautilus_window_slot_open_location_full (NautilusWindowSlot *slot, old_selection = NULL; if (slot->details->content_view != NULL) { - old_selection = nautilus_view_get_selection (slot->details->content_view); + old_selection = nautilus_files_view_get_selection (slot->details->content_view); } if (target_window == window && target_slot == slot && !is_desktop && @@ -834,7 +834,7 @@ begin_location_change (NautilusWindowSlot *slot, /* We are going to change the location, so make sure we stop any loading * or searching of the previous view, so we avoid to be slow */ if (slot->details->content_view) { - nautilus_view_stop_loading (slot->details->content_view); + nautilus_files_view_stop_loading (slot->details->content_view); } /* If there is no new selection and the new location is @@ -905,7 +905,7 @@ begin_location_change (NautilusWindowSlot *slot, /* Set current_bookmark scroll pos */ if (slot->details->current_location_bookmark != NULL && slot->details->content_view != NULL) { - current_pos = nautilus_view_get_first_visible_file (slot->details->content_view); + current_pos = nautilus_files_view_get_first_visible_file (slot->details->content_view); nautilus_bookmark_set_scroll_pos (slot->details->current_location_bookmark, current_pos); g_free (current_pos); } @@ -1213,7 +1213,7 @@ got_file_info_for_view_selection_callback (NautilusFile *file, * so the view mode of the current view will be the one search is using, * which is not the one we are interested in */ if (slot->details->view_mode_before_search == NULL) { - slot->details->view_mode_before_search = g_strdup (nautilus_view_get_view_id (slot->details->content_view)); + slot->details->view_mode_before_search = g_strdup (nautilus_files_view_get_view_id (slot->details->content_view)); } view_id = g_strdup (NAUTILUS_LIST_VIEW_IID); } else { @@ -1231,7 +1231,7 @@ got_file_info_for_view_selection_callback (NautilusFile *file, g_free (slot->details->view_mode_before_search); slot->details->view_mode_before_search = NULL; } else { - view_id = g_strdup (nautilus_view_get_view_id (slot->details->content_view)); + view_id = g_strdup (nautilus_files_view_get_view_id (slot->details->content_view)); } } @@ -1340,7 +1340,7 @@ create_content_view (NautilusWindowSlot *slot, GError **error_out) { NautilusWindow *window; - NautilusView *view; + NautilusFilesView *view; GList *selection; gboolean ret = TRUE; GError *error = NULL; @@ -1371,7 +1371,7 @@ create_content_view (NautilusWindowSlot *slot, g_object_ref (view); } else { /* create a new content view */ - view = nautilus_view_new (view_id, slot); + view = nautilus_files_view_new (view_id, slot); slot->details->new_content_view = view; } @@ -1400,7 +1400,7 @@ create_content_view (NautilusWindowSlot *slot, slot->details->load_with_search = FALSE; if (slot->details->pending_selection == NULL) { - slot->details->pending_selection = nautilus_view_get_selection (slot->details->content_view); + slot->details->pending_selection = nautilus_files_view_get_selection (slot->details->content_view); } } @@ -1416,7 +1416,7 @@ create_content_view (NautilusWindowSlot *slot, g_list_free_full (slot->details->pending_selection, g_object_unref); slot->details->pending_selection = NULL; } else if (old_location != NULL) { - selection = nautilus_view_get_selection (slot->details->content_view); + selection = nautilus_files_view_get_selection (slot->details->content_view); load_new_location (slot, old_location, selection, @@ -1448,7 +1448,7 @@ load_new_location (NautilusWindowSlot *slot, gboolean tell_new_content_view) { GList *selection_copy; - NautilusView *view; + NautilusFilesView *view; g_assert (slot != NULL); g_assert (location != NULL); @@ -1460,19 +1460,19 @@ load_new_location (NautilusWindowSlot *slot, /* Note, these may recurse into report_load_underway */ if (slot->details->content_view != NULL && tell_current_content_view) { view = slot->details->content_view; - nautilus_view_load_location (slot->details->content_view, location); + nautilus_files_view_load_location (slot->details->content_view, location); } if (slot->details->new_content_view != NULL && tell_new_content_view && (!tell_current_content_view || slot->details->new_content_view != slot->details->content_view) ) { view = slot->details->new_content_view; - nautilus_view_load_location (slot->details->new_content_view, location); + nautilus_files_view_load_location (slot->details->new_content_view, location); } if (view != NULL) { /* new_content_view might have changed here if report_load_underway was called from load_location */ - nautilus_view_set_selection (view, selection_copy); + nautilus_files_view_set_selection (view, selection_copy); } g_list_free_full (selection_copy, g_object_unref); @@ -1542,7 +1542,7 @@ cancel_location_change (NautilusWindowSlot *slot) directory = nautilus_directory_get (slot->details->location); /* Stops current loading or search if any, so we are not slow */ - nautilus_view_stop_loading (slot->details->content_view); + nautilus_files_view_stop_loading (slot->details->content_view); nautilus_directory_unref (directory); if (slot->details->pending_location != NULL @@ -1554,7 +1554,7 @@ cancel_location_change (NautilusWindowSlot *slot) * be told, or it is the very pending change we wish * to cancel. */ - selection = nautilus_view_get_selection (slot->details->content_view); + selection = nautilus_files_view_get_selection (slot->details->content_view); load_new_location (slot, location, selection, @@ -1654,10 +1654,10 @@ nautilus_window_slot_set_content_view (NautilusWindowSlot *slot, nautilus_window_slot_set_allow_stop (slot, TRUE); - if (nautilus_view_get_selection_count (slot->details->content_view) == 0) { + if (nautilus_files_view_get_selection_count (slot->details->content_view) == 0) { /* If there is no selection, queue a scroll to the same icon that * is currently visible */ - slot->details->pending_scroll_to = nautilus_view_get_first_visible_file (slot->details->content_view); + slot->details->pending_scroll_to = nautilus_files_view_get_first_visible_file (slot->details->content_view); } slot->details->location_change_type = NAUTILUS_LOCATION_CHANGE_RELOAD; @@ -1740,8 +1740,8 @@ nautilus_window_slot_force_reload (NautilusWindowSlot *slot) current_pos = NULL; selection = NULL; if (slot->details->content_view != NULL) { - current_pos = nautilus_view_get_first_visible_file (slot->details->content_view); - selection = nautilus_view_get_selection (slot->details->content_view); + current_pos = nautilus_files_view_get_first_visible_file (slot->details->content_view); + selection = nautilus_files_view_get_selection (slot->details->content_view); } begin_location_change (slot, location, location, selection, @@ -1763,7 +1763,7 @@ nautilus_window_slot_queue_reload (NautilusWindowSlot *slot) if (slot->details->pending_location != NULL || slot->details->content_view == NULL - || nautilus_view_get_loading (slot->details->content_view)) { + || nautilus_files_view_get_loading (slot->details->content_view)) { /* there is a reload in flight */ slot->details->needs_reload = TRUE; return; @@ -2038,7 +2038,7 @@ static void nautilus_window_slot_show_trash_bar (NautilusWindowSlot *slot) { GtkWidget *bar; - NautilusView *view; + NautilusFilesView *view; view = nautilus_window_slot_get_current_view (slot); bar = nautilus_trash_bar_new (view); @@ -2129,7 +2129,7 @@ nautilus_window_slot_update_for_new_location (NautilusWindowSlot *slot) } static void -view_end_loading_cb (NautilusView *view, +view_end_loading_cb (NautilusFilesView *view, gboolean all_files_seen, NautilusWindowSlot *slot) { @@ -2137,7 +2137,7 @@ view_end_loading_cb (NautilusView *view, * Don't handle it if its from an old view we've switched from */ if (view == slot->details->content_view && all_files_seen) { if (slot->details->pending_scroll_to != NULL) { - nautilus_view_scroll_to_file (slot->details->content_view, + nautilus_files_view_scroll_to_file (slot->details->content_view, slot->details->pending_scroll_to); } end_location_change (slot); @@ -2152,7 +2152,7 @@ view_end_loading_cb (NautilusView *view, } static void -view_begin_loading_cb (NautilusView *view, +view_begin_loading_cb (NautilusFilesView *view, NautilusWindowSlot *slot) { nautilus_profile_start (NULL); @@ -2522,7 +2522,7 @@ nautilus_window_slot_set_window (NautilusWindowSlot *slot, } } -NautilusView * +NautilusFilesView * nautilus_window_slot_get_view (NautilusWindowSlot *slot) { return slot->details->content_view; @@ -2606,7 +2606,7 @@ nautilus_window_slot_get_current_uri (NautilusWindowSlot *slot) return NULL; } -NautilusView * +NautilusFilesView * nautilus_window_slot_get_current_view (NautilusWindowSlot *slot) { if (slot->details->content_view != NULL) { @@ -2685,23 +2685,23 @@ nautilus_window_slot_new (NautilusWindow *window) GIcon* nautilus_window_slot_get_icon (NautilusWindowSlot *slot) { - NautilusView *view; + NautilusFilesView *view; g_return_val_if_fail (NAUTILUS_IS_WINDOW_SLOT (slot), NULL); view = nautilus_window_slot_get_current_view (slot); - return view ? nautilus_view_get_icon (view) : NULL; + return view ? nautilus_files_view_get_icon (view) : NULL; } GtkWidget* nautilus_window_slot_get_view_widget (NautilusWindowSlot *slot) { - NautilusView *view; + NautilusFilesView *view; g_return_val_if_fail (NAUTILUS_IS_WINDOW_SLOT (slot), NULL); view = nautilus_window_slot_get_current_view (slot); - return view ? nautilus_view_get_view_widget (view) : NULL; + return view ? nautilus_files_view_get_view_widget (view) : NULL; } diff --git a/src/nautilus-window-slot.h b/src/nautilus-window-slot.h index 36d27bc27..fc433fff5 100644 --- a/src/nautilus-window-slot.h +++ b/src/nautilus-window-slot.h @@ -29,7 +29,7 @@ typedef struct NautilusWindowSlot NautilusWindowSlot; typedef struct NautilusWindowSlotClass NautilusWindowSlotClass; typedef struct NautilusWindowSlotDetails NautilusWindowSlotDetails; -#include "nautilus-view.h" +#include "nautilus-files-view.h" #include "nautilus-window.h" #define NAUTILUS_TYPE_WINDOW_SLOT (nautilus_window_slot_get_type()) @@ -55,7 +55,7 @@ struct NautilusWindowSlotClass { }; /* Each NautilusWindowSlot corresponds to a location in the window - * for displaying a NautilusView, i.e. a tab. + * for displaying a NautilusFilesView, i.e. a tab. */ struct NautilusWindowSlot { GtkBox parent; @@ -87,9 +87,9 @@ char * nautilus_window_slot_get_location_uri (NautilusWindowSlot *slot); NautilusFile * nautilus_window_slot_get_file (NautilusWindowSlot *slot); NautilusBookmark *nautilus_window_slot_get_bookmark (NautilusWindowSlot *slot); -NautilusView * nautilus_window_slot_get_view (NautilusWindowSlot *slot); +NautilusFilesView * nautilus_window_slot_get_view (NautilusWindowSlot *slot); -NautilusView * nautilus_window_slot_get_current_view (NautilusWindowSlot *slot); +NautilusFilesView * nautilus_window_slot_get_current_view (NautilusWindowSlot *slot); char * nautilus_window_slot_get_current_uri (NautilusWindowSlot *slot); GList * nautilus_window_slot_get_back_history (NautilusWindowSlot *slot); diff --git a/src/nautilus-window.h b/src/nautilus-window.h index 7bb3e2d04..2bffe051e 100644 --- a/src/nautilus-window.h +++ b/src/nautilus-window.h @@ -54,7 +54,7 @@ typedef gboolean (* NautilusWindowGoToCallback) (NautilusWindow *window, GError *error, gpointer user_data); -#include "nautilus-view.h" +#include "nautilus-files-view.h" #include "nautilus-window-slot.h" #define NAUTILUS_TYPE_WINDOW nautilus_window_get_type() diff --git a/src/nautilus.gresource.xml b/src/nautilus.gresource.xml index c80a529d4..5a3e324e9 100644 --- a/src/nautilus.gresource.xml +++ b/src/nautilus.gresource.xml @@ -10,7 +10,7 @@ <file>nautilus-toolbar-action-menu.xml</file> <file>nautilus-create-folder-dialog.ui</file> <file>nautilus-rename-file-popover.ui</file> - <file>nautilus-view-context-menus.xml</file> + <file>nautilus-files-view-context-menus.xml</file> <file>nautilus-progress-info-widget.xml</file> <file>nautilus-move-to-trash-shortcut-changed.ui</file> <file>nautilus-window.ui</file> |