1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 
3 /* nemo-view.c
4  *
5  * Copyright (C) 1999, 2000  Free Software Foundation
6  * Copyright (C) 2000, 2001  Eazel, Inc.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of the
11  * License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public
19  * License along with this program; if not, write to the
20  * Free Software Foundation, Inc., 51 Franklin Street - Suite 500,
21  * Boston, MA 02110-1335, USA.
22  *
23  * Authors: Ettore Perazzoli,
24  *          John Sullivan <sullivan@eazel.com>,
25  *          Darin Adler <darin@bentspoon.com>,
26  *          Pavel Cisler <pavel@eazel.com>,
27  *          David Emory Watson <dwatson@cs.ucr.edu>
28  */
29 
30 #include <config.h>
31 
32 #include "nemo-view.h"
33 
34 #include "nemo-actions.h"
35 #include "nemo-desktop-icon-view.h"
36 #include "nemo-error-reporting.h"
37 #include "nemo-list-view.h"
38 #include "nemo-mime-actions.h"
39 #include "nemo-previewer.h"
40 #include "nemo-properties-window.h"
41 #include "nemo-bookmark-list.h"
42 #include "nemo-directory-private.h"
43 
44 #include <sys/stat.h>
45 #include <fcntl.h>
46 
47 #include <gdk/gdkx.h>
48 #include <gdk/gdkkeysyms.h>
49 #include <gtk/gtk.h>
50 #include <glib.h>
51 #include <glib/gi18n.h>
52 #include <glib/gstdio.h>
53 #include <gio/gio.h>
54 #include <math.h>
55 
56 #include <eel/eel-glib-extensions.h>
57 #include <eel/eel-gnome-extensions.h>
58 #include <eel/eel-gtk-extensions.h>
59 #include <eel/eel-stock-dialogs.h>
60 #include <eel/eel-string.h>
61 #include <eel/eel-vfs-extensions.h>
62 
63 #include <libnemo-extension/nemo-menu-provider.h>
64 #include <libnemo-private/nemo-bookmark.h>
65 #include <libnemo-private/nemo-clipboard.h>
66 #include <libnemo-private/nemo-clipboard-monitor.h>
67 #include <libnemo-private/nemo-desktop-icon-file.h>
68 #include <libnemo-private/nemo-desktop-directory.h>
69 #include <libnemo-private/nemo-search-directory.h>
70 #include <libnemo-private/nemo-directory.h>
71 #include <libnemo-private/nemo-dnd.h>
72 #include <libnemo-private/nemo-file-attributes.h>
73 #include <libnemo-private/nemo-file-changes-queue.h>
74 #include <libnemo-private/nemo-file-dnd.h>
75 #include <libnemo-private/nemo-file-operations.h>
76 #include <libnemo-private/nemo-file-utilities.h>
77 #include <libnemo-private/nemo-file-private.h>
78 #include <libnemo-private/nemo-global-preferences.h>
79 #include <libnemo-private/nemo-link.h>
80 #include <libnemo-private/nemo-metadata.h>
81 #include <libnemo-private/nemo-recent.h>
82 #include <libnemo-private/nemo-module.h>
83 #include <libnemo-private/nemo-program-choosing.h>
84 #include <libnemo-private/nemo-trash-monitor.h>
85 #include <libnemo-private/nemo-ui-utilities.h>
86 #include <libnemo-private/nemo-signaller.h>
87 #include <libnemo-private/nemo-icon-names.h>
88 #include <libnemo-private/nemo-file-undo-manager.h>
89 #include <libnemo-private/nemo-action.h>
90 #include <libnemo-private/nemo-widget-action.h>
91 #include <libnemo-private/nemo-separator-action.h>
92 #include <libnemo-private/nemo-action-manager.h>
93 #include <libnemo-private/nemo-mime-application-chooser.h>
94 
95 #define DEBUG_FLAG NEMO_DEBUG_DIRECTORY_VIEW
96 #include <libnemo-private/nemo-debug.h>
97 
98 /* Minimum starting update inverval */
99 #define UPDATE_INTERVAL_MIN 200
100 /* Maximum update interval */
101 #define UPDATE_INTERVAL_MAX 2000
102 /* Amount of miliseconds the update interval is increased */
103 #define UPDATE_INTERVAL_INC 250
104 /* Interval at which the update interval is increased */
105 #define UPDATE_INTERVAL_TIMEOUT_INTERVAL 500
106 /* Milliseconds that have to pass without a change to reset the update interval */
107 #define UPDATE_INTERVAL_RESET 1000
108 
109 #define SILENT_WINDOW_OPEN_LIMIT 5
110 
111 #define DUPLICATE_HORIZONTAL_ICON_OFFSET 70
112 #define DUPLICATE_VERTICAL_ICON_OFFSET   30
113 
114 #define MAX_QUEUED_UPDATES 250
115 
116 #define NEMO_VIEW_MENU_PATH_OPEN_PLACEHOLDER                  "/MenuBar/File/Open Placeholder"
117 #define NEMO_VIEW_MENU_PATH_APPLICATIONS_SUBMENU_PLACEHOLDER  "/MenuBar/File/Open Placeholder/Open With/Applications Placeholder"
118 #define NEMO_VIEW_MENU_PATH_APPLICATIONS_PLACEHOLDER    	  "/MenuBar/File/Open Placeholder/Applications Placeholder"
119 #define NEMO_VIEW_MENU_PATH_SCRIPTS_PLACEHOLDER               "/MenuBar/File/Open Placeholder/Scripts/Scripts Placeholder"
120 #define NEMO_VIEW_MENU_PATH_ACTIONS_PLACEHOLDER               "/MenuBar/File/Open Placeholder/ActionsPlaceholder"
121 #define NEMO_VIEW_MENU_PATH_EXTENSION_ACTIONS_PLACEHOLDER     "/MenuBar/Edit/Extension Actions"
122 #define NEMO_VIEW_MENU_PATH_NEW_DOCUMENTS_PLACEHOLDER  	  "/MenuBar/File/New Items Placeholder/New Documents/New Documents Placeholder"
123 #define NEMO_VIEW_MENU_PATH_OPEN				  "/MenuBar/File/Open Placeholder/Open"
124 
125 #define NEMO_VIEW_POPUP_PATH_SELECTION            "/selection"
126 #define NEMO_VIEW_POPUP_PATH_OPEN_PLACEHOLDER	  "/selection/Open Placeholder"
127 #define NEMO_VIEW_POPUP_PATH_APPLICATIONS_SUBMENU_PLACEHOLDER "/selection/Open Placeholder/Open With/Applications Placeholder"
128 #define NEMO_VIEW_POPUP_PATH_APPLICATIONS_PLACEHOLDER    	  "/selection/Open Placeholder/Applications Placeholder"
129 #define NEMO_VIEW_POPUP_PATH_SCRIPTS_PLACEHOLDER    	  "/selection/Open Placeholder/Scripts/Scripts Placeholder"
130 #define NEMO_VIEW_POPUP_PATH_ACTIONS_PLACEHOLDER           "/selection/Open Placeholder/ActionsPlaceholder"
131 #define NEMO_VIEW_POPUP_PATH_EXTENSION_ACTIONS		  "/selection/Extension Actions"
132 #define NEMO_VIEW_POPUP_PATH_OPEN				  "/selection/Open Placeholder/Open"
133 
134 #define NEMO_VIEW_POPUP_PATH_BACKGROUND			  "/background"
135 #define NEMO_VIEW_POPUP_PATH_BACKGROUND_SCRIPTS_PLACEHOLDER	  "/background/Before Zoom Items/New Object Items/Scripts/Scripts Placeholder"
136 #define NEMO_VIEW_POPUP_PATH_BACKGROUND_ACTIONS_PLACEHOLDER   "/background/Before Zoom Items/New Object Items/ActionsPlaceholder"
137 #define NEMO_VIEW_POPUP_PATH_BACKGROUND_NEW_DOCUMENTS_PLACEHOLDER "/background/Before Zoom Items/New Object Items/New Documents/New Documents Placeholder"
138 
139 #define NEMO_VIEW_POPUP_PATH_LOCATION			  "/location"
140 
141 #define NEMO_VIEW_POPUP_PATH_BOOKMARK_MOVETO_ENTRIES_PLACEHOLDER "/selection/File Actions/MoveToMenu/BookmarkMoveToPlaceHolder"
142 #define NEMO_VIEW_POPUP_PATH_BOOKMARK_COPYTO_ENTRIES_PLACEHOLDER "/selection/File Actions/CopyToMenu/BookmarkCopyToPlaceHolder"
143 #define NEMO_VIEW_MENU_PATH_BOOKMARK_MOVETO_ENTRIES_PLACEHOLDER "/MenuBar/Edit/File Items Placeholder/MoveToMenu/BookmarkMoveToPlaceHolder"
144 #define NEMO_VIEW_MENU_PATH_BOOKMARK_COPYTO_ENTRIES_PLACEHOLDER "/MenuBar/Edit/File Items Placeholder/CopyToMenu/BookmarkCopyToPlaceHolder"
145 
146 #define NEMO_VIEW_POPUP_PATH_PLACES_MOVETO_ENTRIES_PLACEHOLDER "/selection/File Actions/MoveToMenu/PlacesMoveToPlaceHolder"
147 #define NEMO_VIEW_POPUP_PATH_PLACES_COPYTO_ENTRIES_PLACEHOLDER "/selection/File Actions/CopyToMenu/PlacesCopyToPlaceHolder"
148 #define NEMO_VIEW_MENU_PATH_PLACES_MOVETO_ENTRIES_PLACEHOLDER "/MenuBar/Edit/File Items Placeholder/MoveToMenu/PlacesMoveToPlaceHolder"
149 #define NEMO_VIEW_MENU_PATH_PLACES_COPYTO_ENTRIES_PLACEHOLDER "/MenuBar/Edit/File Items Placeholder/CopyToMenu/PlacesCopyToPlaceHolder"
150 
151 #define MAX_MENU_LEVELS 5
152 #define TEMPLATE_LIMIT 30
153 
154 enum {
155 	ADD_FILE,
156 	BEGIN_FILE_CHANGES,
157 	BEGIN_LOADING,
158 	CLEAR,
159 	END_FILE_CHANGES,
160 	END_LOADING,
161 	FILE_CHANGED,
162 	LOAD_ERROR,
163 	MOVE_COPY_ITEMS,
164 	REMOVE_FILE,
165 	ZOOM_LEVEL_CHANGED,
166 	SELECTION_CHANGED,
167 	TRASH,
168 	DELETE,
169 	LAST_SIGNAL
170 };
171 
172 enum {
173 	PROP_WINDOW_SLOT = 1,
174 	PROP_SUPPORTS_ZOOMING,
175 	NUM_PROPERTIES
176 };
177 
178 static guint signals[LAST_SIGNAL] = { 0 };
179 static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
180 
181 static GdkAtom copied_files_atom;
182 
183 static char *scripts_directory_uri = NULL;
184 static int scripts_directory_uri_length;
185 
186 struct NemoViewDetails
187 {
188 	NemoWindow *window;
189 	NemoWindowSlot *slot;
190 	NemoDirectory *model;
191 	NemoFile *directory_as_file;
192 	NemoFile *location_popup_directory_as_file;
193 	NemoBookmarkList *bookmarks;
194 	GdkEventButton *location_popup_event;
195 	GtkActionGroup *dir_action_group;
196 	guint dir_merge_id;
197 
198 	gboolean supports_zooming;
199 
200 	GList *scripts_directory_list;
201 	GtkActionGroup *scripts_action_group;
202 	guint scripts_merge_id;
203 
204     GtkActionGroup *actions_action_group;
205     guint actions_merge_id;
206     guint action_manager_changed_id;
207     NemoActionManager *action_manager;
208 
209 	GList *templates_directory_list;
210 	GtkActionGroup *templates_action_group;
211 	guint templates_merge_id;
212 
213 	GtkActionGroup *extensions_menu_action_group;
214 	guint extensions_menu_merge_id;
215 
216 	guint display_selection_idle_id;
217 	guint update_menus_timeout_id;
218 	guint update_status_idle_id;
219 	guint reveal_selection_idle_id;
220 
221 	guint display_pending_source_id;
222 	guint changes_timeout_id;
223 
224 	guint update_interval;
225  	guint64 last_queued;
226 
227 	guint files_added_handler_id;
228 	guint files_changed_handler_id;
229 	guint load_error_handler_id;
230 	guint done_loading_handler_id;
231 	guint file_changed_handler_id;
232 
233 	guint delayed_rename_file_id;
234 
235 	GList *new_added_files;
236 	GList *new_changed_files;
237 
238 	GHashTable *non_ready_files;
239 
240 	GList *old_added_files;
241 	GList *old_changed_files;
242 
243 	GList *pending_selection;
244 
245 	/* whether we are in the active slot */
246 	gboolean active;
247 
248 	/* loading indicates whether this view has begun loading a directory.
249 	 * This flag should need not be set inside subclasses. NemoView automatically
250 	 * sets 'loading' to TRUE before it begins loading a directory's contents and to FALSE
251 	 * after it finishes loading the directory and its view.
252 	 */
253 	gboolean loading;
254 	gboolean menu_states_untrustworthy;
255 	gboolean scripts_invalid;
256 	gboolean templates_invalid;
257     gboolean actions_invalid;
258 	gboolean reported_load_error;
259 
260 	/* flag to indicate that no file updates should be dispatched to subclasses.
261 	 * This is a workaround for bug #87701 that prevents the list view from
262 	 * losing focus when the underlying GtkTreeView is updated.
263 	 */
264 	gboolean updates_frozen;
265 	guint	 updates_queued;
266 	gboolean needs_reload;
267 
268 	gboolean is_renaming;
269 
270 	gboolean sort_directories_first;
271 
272 	gboolean show_foreign_files;
273 	gboolean show_hidden_files;
274 	gboolean ignore_hidden_file_preferences;
275 
276 	gboolean batching_selection_level;
277 	gboolean selection_changed_while_batched;
278 
279 	gboolean selection_was_removed;
280 
281 	gboolean metadata_for_directory_as_file_pending;
282 	gboolean metadata_for_files_in_directory_pending;
283 
284 	gboolean selection_change_is_due_to_shell;
285 	gboolean send_selection_change_to_shell;
286 
287 	GtkActionGroup *open_with_action_group;
288 	guint open_with_merge_id;
289 
290 	GList *subdirectory_list;
291 
292     guint copy_move_merge_ids[4];
293     GtkActionGroup *copy_move_action_groups[4];
294     guint bookmarks_changed_id;
295 
296 	GdkPoint context_menu_position;
297 
298     gboolean showing_bookmarks_in_to_menus;
299     gboolean showing_places_in_to_menus;
300 
301     GVolumeMonitor *volume_monitor;
302 
303     GTimer *load_timer;
304 };
305 
306 typedef struct {
307 	NemoFile *file;
308 	NemoDirectory *directory;
309 } FileAndDirectory;
310 
311 /* forward declarations */
312 
313 static gboolean display_selection_info_idle_callback           (gpointer              data);
314 static void     nemo_view_duplicate_selection              (NemoView      *view,
315 							        GList                *files,
316 							        GArray               *item_locations);
317 static void     nemo_view_create_links_for_files           (NemoView      *view,
318 							        GList                *files,
319 							        GArray               *item_locations);
320 static void     trash_or_delete_files                          (GtkWindow            *parent_window,
321 								const GList          *files,
322 								gboolean              delete_if_all_already_in_trash,
323 								NemoView      *view);
324 static void     load_directory                                 (NemoView      *view,
325 								NemoDirectory    *directory);
326 static void     nemo_view_merge_menus                      (NemoView      *view);
327 static void     nemo_view_unmerge_menus                    (NemoView      *view);
328 static void     nemo_view_init_show_hidden_files           (NemoView      *view);
329 static void     clipboard_changed_callback                     (NemoClipboardMonitor *monitor,
330 								NemoView      *view);
331 static void     open_one_in_new_window                         (gpointer              data,
332 								gpointer              callback_data);
333 static void     schedule_update_menus                          (NemoView      *view);
334 static void     schedule_update_menus_callback                 (gpointer              callback_data);
335 static void     remove_update_menus_timeout_callback           (NemoView      *view);
336 static void     schedule_update_status                          (NemoView      *view);
337 static void     remove_update_status_idle_callback             (NemoView *view);
338 static void     reset_update_interval                          (NemoView      *view);
339 static void     schedule_idle_display_of_pending_files         (NemoView      *view);
340 static void     unschedule_display_of_pending_files            (NemoView      *view);
341 static void     disconnect_model_handlers                      (NemoView      *view);
342 static void     metadata_for_directory_as_file_ready_callback  (NemoFile         *file,
343 								gpointer              callback_data);
344 static void     metadata_for_files_in_directory_ready_callback (NemoDirectory    *directory,
345 								GList                *files,
346 								gpointer              callback_data);
347 static void     nemo_view_trash_state_changed_callback     (NemoTrashMonitor *trash,
348 							        gboolean              state,
349 							        gpointer              callback_data);
350 static void     nemo_view_select_file                      (NemoView      *view,
351 							        NemoFile         *file);
352 
353 static void     update_templates_directory                     (NemoView *view);
354 static void     user_dirs_changed                              (NemoView *view);
355 
356 static gboolean file_list_all_are_folders                      (GList *file_list);
357 
358 static void unschedule_pop_up_location_context_menu (NemoView *view);
359 static void disconnect_bookmark_signals (NemoView *view);
360 static void run_action_callback (NemoAction *action, gpointer callback_data);
361 
362 G_DEFINE_TYPE (NemoView, nemo_view, GTK_TYPE_SCROLLED_WINDOW);
363 #define parent_class nemo_view_parent_class
364 
365 /* virtual methods (public and non-public) */
366 
367 /**
368  * nemo_view_merge_menus:
369  *
370  * Add this view's menus to the window's menu bar.
371  * @view: NemoView in question.
372  */
373 static void
nemo_view_merge_menus(NemoView * view)374 nemo_view_merge_menus (NemoView *view)
375 {
376 	g_return_if_fail (NEMO_IS_VIEW (view));
377 
378 	NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->merge_menus (view);
379 }
380 
381 static void
nemo_view_unmerge_menus(NemoView * view)382 nemo_view_unmerge_menus (NemoView *view)
383 {
384 	g_return_if_fail (NEMO_IS_VIEW (view));
385 
386 	NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->unmerge_menus (view);}
387 
388 static char *
real_get_backing_uri(NemoView * view)389 real_get_backing_uri (NemoView *view)
390 {
391 	NemoDirectory *directory;
392 	char *uri;
393 
394 	g_return_val_if_fail (NEMO_IS_VIEW (view), NULL);
395 
396 	if (view->details->model == NULL) {
397 		return NULL;
398 	}
399 
400 	directory = view->details->model;
401 
402 	if (NEMO_IS_DESKTOP_DIRECTORY (directory)) {
403 		directory = nemo_desktop_directory_get_real_directory (NEMO_DESKTOP_DIRECTORY (directory));
404 	} else {
405 		nemo_directory_ref (directory);
406 	}
407 
408 	uri = nemo_directory_get_uri (directory);
409 
410 	nemo_directory_unref (directory);
411 
412 	return uri;
413 }
414 
415 /**
416  *
417  * nemo_view_get_backing_uri:
418  *
419  * Returns the URI for the target location of new directory, new file, new
420  * link and paste operations.
421  */
422 
423 char *
nemo_view_get_backing_uri(NemoView * view)424 nemo_view_get_backing_uri (NemoView *view)
425 {
426 	g_return_val_if_fail (NEMO_IS_VIEW (view), NULL);
427 
428 	return NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->get_backing_uri (view);
429 }
430 
431 /**
432  * nemo_view_select_all:
433  *
434  * select all the items in the view
435  *
436  **/
437 static void
nemo_view_select_all(NemoView * view)438 nemo_view_select_all (NemoView *view)
439 {
440 	g_return_if_fail (NEMO_IS_VIEW (view));
441 
442 	NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->select_all (view);
443 }
444 
445 static void
nemo_view_call_set_selection(NemoView * view,GList * selection)446 nemo_view_call_set_selection (NemoView *view, GList *selection)
447 {
448 	g_return_if_fail (NEMO_IS_VIEW (view));
449 
450 	NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->set_selection (view, selection);
451 }
452 
453 static GList *
nemo_view_get_selection_for_file_transfer(NemoView * view)454 nemo_view_get_selection_for_file_transfer (NemoView *view)
455 {
456 	g_return_val_if_fail (NEMO_IS_VIEW (view), NULL);
457 
458 	return NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->get_selection_for_file_transfer (view);
459 }
460 
461 /**
462  * nemo_view_get_selected_icon_locations:
463  *
464  * return an array of locations of selected icons if available
465  * Return value: GArray of GdkPoints
466  *
467  **/
468 static GArray *
nemo_view_get_selected_icon_locations(NemoView * view)469 nemo_view_get_selected_icon_locations (NemoView *view)
470 {
471 	g_return_val_if_fail (NEMO_IS_VIEW (view), NULL);
472 
473 	return NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->get_selected_icon_locations (view);
474 }
475 
476 static void
nemo_view_invert_selection(NemoView * view)477 nemo_view_invert_selection (NemoView *view)
478 {
479 	g_return_if_fail (NEMO_IS_VIEW (view));
480 
481 	NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->invert_selection (view);
482 }
483 
484 /**
485  * nemo_view_reveal_selection:
486  *
487  * Scroll as necessary to reveal the selected items.
488  **/
489 static void
nemo_view_reveal_selection(NemoView * view)490 nemo_view_reveal_selection (NemoView *view)
491 {
492 	g_return_if_fail (NEMO_IS_VIEW (view));
493 
494 	NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->reveal_selection (view);
495 }
496 
497 /**
498  * nemo_view_reset_to_defaults:
499  *
500  * set sorting order, zoom level, etc. to match defaults
501  *
502  **/
503 static void
nemo_view_reset_to_defaults(NemoView * view)504 nemo_view_reset_to_defaults (NemoView *view)
505 {
506     NemoFile *file;
507     NemoWindow *window;
508     g_return_if_fail (NEMO_IS_VIEW (view));
509 
510     NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->reset_to_defaults (view);
511 
512     gboolean show_hidden = g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_SHOW_HIDDEN_FILES);
513 
514     window = view->details->window;
515     if (show_hidden) {
516         nemo_window_set_hidden_files_mode (window, NEMO_WINDOW_SHOW_HIDDEN_FILES_ENABLE);
517     } else {
518         nemo_window_set_hidden_files_mode (window, NEMO_WINDOW_SHOW_HIDDEN_FILES_DISABLE);
519     }
520 
521     file = view->details->slot->viewed_file;
522     nemo_file_set_metadata(file, NEMO_METADATA_KEY_SHOW_THUMBNAILS, NULL, NULL);
523     nemo_file_set_metadata(file, NEMO_METADATA_KEY_DEFAULT_VIEW, NULL, NULL);
524     gtk_action_activate (gtk_action_group_get_action (nemo_window_get_main_action_group (window), NEMO_ACTION_RELOAD));
525 }
526 
527 static gboolean
nemo_view_using_manual_layout(NemoView * view)528 nemo_view_using_manual_layout (NemoView  *view)
529 {
530 	g_return_val_if_fail (NEMO_IS_VIEW (view), FALSE);
531 
532 	return 	NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->using_manual_layout (view);
533 }
534 
535 static guint
nemo_view_get_item_count(NemoView * view)536 nemo_view_get_item_count (NemoView *view)
537 {
538 	g_return_val_if_fail (NEMO_IS_VIEW (view), 0);
539 
540 	return 	NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->get_item_count (view);
541 }
542 
543 /**
544  * nemo_view_can_rename_file
545  *
546  * Determine whether a file can be renamed.
547  * @file: A NemoFile
548  *
549  * Return value: TRUE if @file can be renamed, FALSE otherwise.
550  *
551  **/
552 static gboolean
nemo_view_can_rename_file(NemoView * view,NemoFile * file)553 nemo_view_can_rename_file (NemoView *view, NemoFile *file)
554 {
555 	return 	NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->can_rename_file (view, file);
556 }
557 
558 static gboolean
nemo_view_is_read_only(NemoView * view)559 nemo_view_is_read_only (NemoView *view)
560 {
561 	g_return_val_if_fail (NEMO_IS_VIEW (view), FALSE);
562 
563 	return 	NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->is_read_only (view);
564 }
565 
566 static gboolean
showing_trash_directory(NemoView * view)567 showing_trash_directory (NemoView *view)
568 {
569 	NemoFile *file;
570 
571 	file = nemo_view_get_directory_as_file (view);
572 	if (file != NULL) {
573 		return nemo_file_is_in_trash (file);
574 	}
575 	return FALSE;
576 }
577 
578 static gboolean
showing_recent_directory(NemoView * view)579 showing_recent_directory (NemoView *view)
580 {
581    NemoFile *file;
582 
583    file = nemo_view_get_directory_as_file (view);
584    if (file != NULL) {
585        return nemo_file_is_in_recent (file);
586    }
587    return FALSE;
588 }
589 
590 static gboolean
showing_favorites_directory(NemoView * view)591 showing_favorites_directory (NemoView *view)
592 {
593    NemoFile *file;
594 
595    file = nemo_view_get_directory_as_file (view);
596    if (file != NULL) {
597        return nemo_file_is_in_favorites (file);
598    }
599    return FALSE;
600 }
601 
602 static gboolean
nemo_view_supports_creating_files(NemoView * view)603 nemo_view_supports_creating_files (NemoView *view)
604 {
605 	g_return_val_if_fail (NEMO_IS_VIEW (view), FALSE);
606 
607     return !nemo_view_is_read_only (view)
608            && !showing_trash_directory (view)
609            && !showing_recent_directory (view)
610            && !showing_favorites_directory (view);
611 }
612 
613 static gboolean
nemo_view_is_empty(NemoView * view)614 nemo_view_is_empty (NemoView *view)
615 {
616 	g_return_val_if_fail (NEMO_IS_VIEW (view), FALSE);
617 
618 	return 	NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->is_empty (view);
619 }
620 
621 /**
622  * nemo_view_bump_zoom_level:
623  *
624  * bump the current zoom level by invoking the relevant subclass through the slot
625  *
626  **/
627 void
nemo_view_bump_zoom_level(NemoView * view,int zoom_increment)628 nemo_view_bump_zoom_level (NemoView *view,
629 			       int zoom_increment)
630 {
631 	g_return_if_fail (NEMO_IS_VIEW (view));
632 
633 	if (!nemo_view_supports_zooming (view)) {
634 		return;
635 	}
636 
637 	NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->bump_zoom_level (view, zoom_increment);
638 }
639 
640 /**
641  * nemo_view_zoom_to_level:
642  *
643  * Set the current zoom level by invoking the relevant subclass through the slot
644  *
645  **/
646 void
nemo_view_zoom_to_level(NemoView * view,NemoZoomLevel zoom_level)647 nemo_view_zoom_to_level (NemoView *view,
648 			     NemoZoomLevel zoom_level)
649 {
650 	g_return_if_fail (NEMO_IS_VIEW (view));
651 
652 	if (!nemo_view_supports_zooming (view)) {
653 		return;
654 	}
655 
656 	NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->zoom_to_level (view, zoom_level);
657 }
658 
659 NemoZoomLevel
nemo_view_get_zoom_level(NemoView * view)660 nemo_view_get_zoom_level (NemoView *view)
661 {
662 	g_return_val_if_fail (NEMO_IS_VIEW (view), NEMO_ZOOM_LEVEL_STANDARD);
663 
664 	if (!nemo_view_supports_zooming (view)) {
665 		return NEMO_ZOOM_LEVEL_STANDARD;
666 	}
667 
668 	return NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->get_zoom_level (view);
669 }
670 
671 /**
672  * nemo_view_can_zoom_in:
673  *
674  * Determine whether the view can be zoomed any closer.
675  * @view: The zoomable NemoView.
676  *
677  * Return value: TRUE if @view can be zoomed any closer, FALSE otherwise.
678  *
679  **/
680 gboolean
nemo_view_can_zoom_in(NemoView * view)681 nemo_view_can_zoom_in (NemoView *view)
682 {
683 	g_return_val_if_fail (NEMO_IS_VIEW (view), FALSE);
684 
685 	if (!nemo_view_supports_zooming (view)) {
686 		return FALSE;
687 	}
688 
689 	return NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->can_zoom_in (view);
690 }
691 
692 /**
693  * nemo_view_can_zoom_out:
694  *
695  * Determine whether the view can be zoomed any further away.
696  * @view: The zoomable NemoView.
697  *
698  * Return value: TRUE if @view can be zoomed any further away, FALSE otherwise.
699  *
700  **/
701 gboolean
nemo_view_can_zoom_out(NemoView * view)702 nemo_view_can_zoom_out (NemoView *view)
703 {
704 	g_return_val_if_fail (NEMO_IS_VIEW (view), FALSE);
705 
706 	if (!nemo_view_supports_zooming (view)) {
707 		return FALSE;
708 	}
709 
710 	return NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->can_zoom_out (view);
711 }
712 
713 gboolean
nemo_view_supports_zooming(NemoView * view)714 nemo_view_supports_zooming (NemoView *view)
715 {
716 	g_return_val_if_fail (NEMO_IS_VIEW (view), FALSE);
717 
718 	return view->details->supports_zooming;
719 }
720 
721 /**
722  * nemo_view_restore_default_zoom_level:
723  *
724  * restore to the default zoom level by invoking the relevant subclass through the slot
725  *
726  **/
727 void
nemo_view_restore_default_zoom_level(NemoView * view)728 nemo_view_restore_default_zoom_level (NemoView *view)
729 {
730 	g_return_if_fail (NEMO_IS_VIEW (view));
731 
732 	if (!nemo_view_supports_zooming (view)) {
733 		return;
734 	}
735 
736 	NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->restore_default_zoom_level (view);
737 }
738 
739 /*
740 static NemoZoomLevel
741 nemo_view_get_default_zoom_level (NemoView *view)
742 {
743     g_return_if_fail (NEMO_IS_VIEW (view));
744 
745     if (!nemo_view_supports_zooming (view)) {
746         return -1;
747     }
748 
749     NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->get_default_zoom_level (view);
750 }
751 */
752 
753 const char *
nemo_view_get_view_id(NemoView * view)754 nemo_view_get_view_id (NemoView *view)
755 {
756 	return NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->get_view_id (view);
757 }
758 
759 char *
nemo_view_get_first_visible_file(NemoView * view)760 nemo_view_get_first_visible_file (NemoView *view)
761 {
762 	return NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->get_first_visible_file (view);
763 }
764 
765 void
nemo_view_scroll_to_file(NemoView * view,const char * uri)766 nemo_view_scroll_to_file (NemoView *view,
767 			      const char *uri)
768 {
769 	NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->scroll_to_file (view, uri);
770 }
771 
772 /**
773  * nemo_view_get_selection:
774  *
775  * Get a list of NemoFile pointers that represents the
776  * currently-selected items in this view. Subclasses must override
777  * the signal handler for the 'get_selection' signal. Callers are
778  * responsible for g_free-ing the list (but not its data).
779  * @view: NemoView whose selected items are of interest.
780  *
781  * Return value: GList of NemoFile pointers representing the selection.
782  *
783  **/
784 GList *
nemo_view_get_selection(NemoView * view)785 nemo_view_get_selection (NemoView *view)
786 {
787 	g_return_val_if_fail (NEMO_IS_VIEW (view), NULL);
788 
789 	return NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->get_selection (view);
790 }
791 
792 /**
793  * nemo_view_peek_selection:
794  *
795  * Get a list of NemoFile pointers that represents the
796  * currently-selected items in this view. Subclasses must override
797  * the signal handler for the 'peek_selection' signal. The returned list
798  * is owned by the view's icon container and should not be freed.
799  * @view: NemoView whose selected items are of interest.
800  *
801  * Return value: GList of NemoFile pointers representing the selection.
802  *
803  **/
804 GList *
nemo_view_peek_selection(NemoView * view)805 nemo_view_peek_selection (NemoView *view)
806 {
807     g_return_val_if_fail (NEMO_IS_VIEW (view), NULL);
808 
809     return NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->peek_selection (view);
810 }
811 
812 // int
813 // nemo_view_get_selection_count (NemoView *view)
814 // {
815 //     g_return_val_if_fail (NEMO_IS_VIEW (view), 0);
816 
817 //     return NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->get_selection_count (view);
818 // }
819 
820 /**
821  * nemo_view_update_menus:
822  *
823  * Update the sensitivity and wording of dynamic menu items.
824  * @view: NemoView in question.
825  */
826 void
nemo_view_update_menus(NemoView * view)827 nemo_view_update_menus (NemoView *view)
828 {
829 	g_return_if_fail (NEMO_IS_VIEW (view));
830 
831 	if (!view->details->active) {
832 		return;
833 	}
834 
835 	NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->update_menus (view);
836 
837 	view->details->menu_states_untrustworthy = FALSE;
838 }
839 
840 typedef struct {
841 	GAppInfo *application;
842 	GList *files;
843 	NemoView *directory_view;
844 } ApplicationLaunchParameters;
845 
846 typedef struct {
847 	NemoFile *file;
848 	NemoView *directory_view;
849 } ScriptLaunchParameters;
850 
851 typedef struct {
852 	NemoFile *file;
853 	NemoView *directory_view;
854 } CreateTemplateParameters;
855 
856 typedef struct {
857 	NemoView *view;
858 	char *dest_uri;
859 } BookmarkCallbackData;
860 
861 
862 static BookmarkCallbackData *
bookmark_callback_data_new(NemoView * view,gchar * uri)863 bookmark_callback_data_new (NemoView *view,
864 							   gchar *uri)
865 {
866     BookmarkCallbackData *result;
867 
868     result = g_new0 (BookmarkCallbackData, 1);
869     result->view = view;
870     result->dest_uri = g_strdup(uri);
871     return result;
872 }
873 
874 static void
bookmark_callback_data_free(BookmarkCallbackData * data)875 bookmark_callback_data_free (BookmarkCallbackData *data)
876 {
877     g_free ((char *)data->dest_uri);
878     g_free (data);
879 }
880 
881 static ApplicationLaunchParameters *
application_launch_parameters_new(GAppInfo * application,GList * files,NemoView * directory_view)882 application_launch_parameters_new (GAppInfo *application,
883 			      	   GList *files,
884 			           NemoView *directory_view)
885 {
886 	ApplicationLaunchParameters *result;
887 
888 	result = g_new0 (ApplicationLaunchParameters, 1);
889 	result->application = g_object_ref (application);
890 	result->files = nemo_file_list_copy (files);
891 
892 	if (directory_view != NULL) {
893 		g_object_ref (directory_view);
894 		result->directory_view = directory_view;
895 	}
896 
897 	return result;
898 }
899 
900 static void
application_launch_parameters_free(ApplicationLaunchParameters * parameters)901 application_launch_parameters_free (ApplicationLaunchParameters *parameters)
902 {
903 	g_object_unref (parameters->application);
904 	nemo_file_list_free (parameters->files);
905 
906 	if (parameters->directory_view != NULL) {
907 		g_object_unref (parameters->directory_view);
908 	}
909 
910 	g_free (parameters);
911 }
912 
913 static GList *
file_and_directory_list_to_files(GList * fad_list)914 file_and_directory_list_to_files (GList *fad_list)
915 {
916 	GList *res, *l;
917 	FileAndDirectory *fad;
918 
919 	res = NULL;
920 	for (l = fad_list; l != NULL; l = l->next) {
921 		fad = l->data;
922 		res = g_list_prepend (res, nemo_file_ref (fad->file));
923 	}
924 	return g_list_reverse (res);
925 }
926 
927 
928 static GList *
file_and_directory_list_from_files(NemoDirectory * directory,GList * files)929 file_and_directory_list_from_files (NemoDirectory *directory, GList *files)
930 {
931 	GList *res, *l;
932 	FileAndDirectory *fad;
933 
934 	res = NULL;
935 	for (l = files; l != NULL; l = l->next) {
936 		fad = g_new0 (FileAndDirectory, 1);
937 		fad->directory = nemo_directory_ref (directory);
938 		fad->file = nemo_file_ref (l->data);
939 		res = g_list_prepend (res, fad);
940 	}
941 	return g_list_reverse (res);
942 }
943 
944 static void
file_and_directory_free(FileAndDirectory * fad)945 file_and_directory_free (FileAndDirectory *fad)
946 {
947 	nemo_directory_unref (fad->directory);
948 	nemo_file_unref (fad->file);
949 	g_free (fad);
950 }
951 
952 
953 static void
file_and_directory_list_free(GList * list)954 file_and_directory_list_free (GList *list)
955 {
956 	GList *l;
957 
958 	for (l = list; l != NULL; l = l->next) {
959 		file_and_directory_free (l->data);
960 	}
961 
962 	g_list_free (list);
963 }
964 
965 static gboolean
file_and_directory_equal(gconstpointer v1,gconstpointer v2)966 file_and_directory_equal (gconstpointer  v1,
967 			  gconstpointer  v2)
968 {
969 	const FileAndDirectory *fad1, *fad2;
970 	fad1 = v1;
971 	fad2 = v2;
972 
973 	return (fad1->file == fad2->file &&
974 		fad1->directory == fad2->directory);
975 }
976 
977 static guint
file_and_directory_hash(gconstpointer v)978 file_and_directory_hash  (gconstpointer  v)
979 {
980 	const FileAndDirectory *fad;
981 
982 	fad = v;
983 	return GPOINTER_TO_UINT (fad->file) ^ GPOINTER_TO_UINT (fad->directory);
984 }
985 
986 
987 
988 
989 static ScriptLaunchParameters *
script_launch_parameters_new(NemoFile * file,NemoView * directory_view)990 script_launch_parameters_new (NemoFile *file,
991 			      NemoView *directory_view)
992 {
993 	ScriptLaunchParameters *result;
994 
995 	result = g_new0 (ScriptLaunchParameters, 1);
996 	g_object_ref (directory_view);
997 	result->directory_view = directory_view;
998 	nemo_file_ref (file);
999 	result->file = file;
1000 
1001 	return result;
1002 }
1003 
1004 static void
script_launch_parameters_free(ScriptLaunchParameters * parameters)1005 script_launch_parameters_free (ScriptLaunchParameters *parameters)
1006 {
1007 	g_object_unref (parameters->directory_view);
1008 	nemo_file_unref (parameters->file);
1009 	g_free (parameters);
1010 }
1011 
1012 static CreateTemplateParameters *
create_template_parameters_new(NemoFile * file,NemoView * directory_view)1013 create_template_parameters_new (NemoFile *file,
1014 				NemoView *directory_view)
1015 {
1016 	CreateTemplateParameters *result;
1017 
1018 	result = g_new0 (CreateTemplateParameters, 1);
1019 	g_object_ref (directory_view);
1020 	result->directory_view = directory_view;
1021 	nemo_file_ref (file);
1022 	result->file = file;
1023 
1024 	return result;
1025 }
1026 
1027 static void
create_templates_parameters_free(CreateTemplateParameters * parameters)1028 create_templates_parameters_free (CreateTemplateParameters *parameters)
1029 {
1030 	g_object_unref (parameters->directory_view);
1031 	nemo_file_unref (parameters->file);
1032 	g_free (parameters);
1033 }
1034 
1035 NemoWindow *
nemo_view_get_nemo_window(NemoView * view)1036 nemo_view_get_nemo_window (NemoView  *view)
1037 {
1038 	g_assert (view->details->window != NULL);
1039 
1040 	return view->details->window;
1041 }
1042 
1043 NemoWindowSlot *
nemo_view_get_nemo_window_slot(NemoView * view)1044 nemo_view_get_nemo_window_slot (NemoView  *view)
1045 {
1046 	g_assert (view->details->slot != NULL);
1047 
1048 	return view->details->slot;
1049 }
1050 
1051 /* Returns the GtkWindow that this directory view occupies, or NULL
1052  * if at the moment this directory view is not in a GtkWindow or the
1053  * GtkWindow cannot be determined. Primarily used for parenting dialogs.
1054  */
1055 static GtkWindow *
nemo_view_get_containing_window(NemoView * view)1056 nemo_view_get_containing_window (NemoView *view)
1057 {
1058 	GtkWidget *window;
1059 
1060 	g_assert (NEMO_IS_VIEW (view));
1061 
1062 	window = gtk_widget_get_ancestor (GTK_WIDGET (view), GTK_TYPE_WINDOW);
1063 	if (window == NULL) {
1064 		return NULL;
1065 	}
1066 
1067 	return GTK_WINDOW (window);
1068 }
1069 
1070 static gboolean
nemo_view_confirm_multiple(GtkWindow * parent_window,int count,gboolean tabs)1071 nemo_view_confirm_multiple (GtkWindow *parent_window,
1072 				int count,
1073 				gboolean tabs)
1074 {
1075 	GtkDialog *dialog;
1076 	char *prompt;
1077 	char *detail;
1078 	int response;
1079 
1080 	if (count <= SILENT_WINDOW_OPEN_LIMIT) {
1081 		return TRUE;
1082 	}
1083 
1084 	prompt = _("Are you sure you want to open all files?");
1085 	if (tabs) {
1086 		detail = g_strdup_printf (ngettext("This will open %'d separate tab.",
1087 						   "This will open %'d separate tabs.", count), count);
1088 	} else {
1089 		detail = g_strdup_printf (ngettext("This will open %'d separate window.",
1090 						   "This will open %'d separate windows.", count), count);
1091 	}
1092 	dialog = eel_show_yes_no_dialog (prompt, detail,
1093 					 GTK_STOCK_OK, GTK_STOCK_CANCEL,
1094 					 parent_window);
1095 	g_free (detail);
1096 
1097 	response = gtk_dialog_run (dialog);
1098 	gtk_widget_destroy (GTK_WIDGET (dialog));
1099 
1100 	return response == GTK_RESPONSE_YES;
1101 }
1102 
1103 static gboolean
selection_contains_one_item_in_menu_callback(NemoView * view,GList * selection)1104 selection_contains_one_item_in_menu_callback (NemoView *view, GList *selection)
1105 {
1106 	if (g_list_length (selection) == 1) {
1107 		return TRUE;
1108 	}
1109 
1110 	/* If we've requested a menu update that hasn't yet occurred, then
1111 	 * the mismatch here doesn't surprise us, and we won't complain.
1112 	 * Otherwise, we will complain.
1113 	 */
1114 	if (!view->details->menu_states_untrustworthy) {
1115 		g_warning ("Expected one selected item, found %'d. No action will be performed.",
1116 			   g_list_length (selection));
1117 	}
1118 
1119 	return FALSE;
1120 }
1121 
1122 static gboolean
selection_not_empty_in_menu_callback(NemoView * view,GList * selection)1123 selection_not_empty_in_menu_callback (NemoView *view, GList *selection)
1124 {
1125 	if (selection != NULL) {
1126 		return TRUE;
1127 	}
1128 
1129 	/* If we've requested a menu update that hasn't yet occurred, then
1130 	 * the mismatch here doesn't surprise us, and we won't complain.
1131 	 * Otherwise, we will complain.
1132 	 */
1133 	if (!view->details->menu_states_untrustworthy) {
1134 		g_warning ("Empty selection found when selection was expected. No action will be performed.");
1135 	}
1136 
1137 	return FALSE;
1138 }
1139 
1140 static char *
get_view_directory(NemoView * view)1141 get_view_directory (NemoView *view)
1142 {
1143 	char *uri, *path;
1144 	GFile *f;
1145 
1146 	uri = nemo_directory_get_uri (view->details->model);
1147 	if (eel_uri_is_desktop (uri)) {
1148 		g_free (uri);
1149 		uri = nemo_get_desktop_directory_uri ();
1150 
1151 	}
1152 	f = g_file_new_for_uri (uri);
1153 	path = g_file_get_path (f);
1154 	g_object_unref (f);
1155 	g_free (uri);
1156 
1157 	return path;
1158 }
1159 
1160 static gboolean
get_is_desktop_view(NemoView * view)1161 get_is_desktop_view (NemoView *view)
1162 {
1163     gchar *uri;
1164     gboolean ret;
1165 
1166     uri = nemo_directory_get_uri (view->details->model);
1167     ret = eel_uri_is_desktop (uri);
1168     g_free (uri);
1169 
1170     return ret;
1171 }
1172 
1173 void
nemo_view_preview_files(NemoView * view,GList * files,GArray * locations)1174 nemo_view_preview_files (NemoView *view,
1175 			     GList *files,
1176 			     GArray *locations)
1177 {
1178 	NemoPreviewer *previewer;
1179 	gchar *uri;
1180 	guint xid;
1181 	GtkWidget *toplevel;
1182 
1183 	previewer = nemo_previewer_get_singleton ();
1184 	uri = nemo_file_get_uri (files->data);
1185 	toplevel = gtk_widget_get_toplevel (GTK_WIDGET (view));
1186 
1187 	xid = gdk_x11_window_get_xid (gtk_widget_get_window (toplevel));
1188 	nemo_previewer_call_show_file (previewer, uri, xid, TRUE);
1189 
1190 	g_free (uri);
1191 }
1192 
1193 void
nemo_view_activate_files(NemoView * view,GList * files,NemoWindowOpenFlags flags,gboolean confirm_multiple)1194 nemo_view_activate_files (NemoView *view,
1195 			      GList *files,
1196 			      NemoWindowOpenFlags flags,
1197 			      gboolean confirm_multiple)
1198 {
1199 	char *path;
1200 
1201 	path = get_view_directory (view);
1202 	nemo_mime_activate_files (nemo_view_get_containing_window (view),
1203 				      view->details->slot,
1204 				      files,
1205 				      path,
1206 				      flags,
1207 				      confirm_multiple);
1208 
1209 	if (get_is_desktop_view(view)) {
1210 		nemo_view_set_selection(view, NULL);
1211 	}
1212 
1213 	g_free (path);
1214 }
1215 
1216 void
nemo_view_activate_file(NemoView * view,NemoFile * file,NemoWindowOpenFlags flags)1217 nemo_view_activate_file (NemoView *view,
1218 			     NemoFile *file,
1219 			     NemoWindowOpenFlags flags)
1220 {
1221 	char *path;
1222 
1223 	path = get_view_directory (view);
1224 	nemo_mime_activate_file (nemo_view_get_containing_window (view),
1225 				     view->details->slot,
1226 				     file,
1227 				     path,
1228 				     flags);
1229 
1230 	if (get_is_desktop_view(view)) {
1231 		nemo_view_set_selection(view, NULL);
1232 	}
1233 
1234 	g_free (path);
1235 }
1236 
1237 static void
action_open_callback(GtkAction * action,gpointer callback_data)1238 action_open_callback (GtkAction *action,
1239 		      gpointer callback_data)
1240 {
1241 	GList *selection;
1242 	NemoView *view;
1243 
1244 	view = NEMO_VIEW (callback_data);
1245 
1246 	selection = nemo_view_get_selection (view);
1247 	nemo_view_activate_files (view,
1248 				      selection,
1249 				      0,
1250 				      TRUE);
1251 	nemo_file_list_free (selection);
1252 }
1253 
1254 static void
action_open_close_parent_callback(GtkAction * action,gpointer callback_data)1255 action_open_close_parent_callback (GtkAction *action,
1256 				   gpointer callback_data)
1257 {
1258 	GList *selection;
1259 	NemoView *view;
1260 
1261 	view = NEMO_VIEW (callback_data);
1262 
1263 	selection = nemo_view_get_selection (view);
1264 	nemo_view_activate_files (view,
1265 				      selection,
1266 				      NEMO_WINDOW_OPEN_FLAG_CLOSE_BEHIND,
1267 				      TRUE);
1268 	nemo_file_list_free (selection);
1269 }
1270 
1271 
1272 static void
action_open_alternate_callback(GtkAction * action,gpointer callback_data)1273 action_open_alternate_callback (GtkAction *action,
1274 				gpointer callback_data)
1275 {
1276 	NemoView *view;
1277 	GList *selection;
1278 	GtkWindow *window;
1279 
1280 	view = NEMO_VIEW (callback_data);
1281 	selection = nemo_view_get_selection (view);
1282 
1283 	window = nemo_view_get_containing_window (view);
1284 
1285 	if (nemo_view_confirm_multiple (window, g_list_length (selection), FALSE)) {
1286 		g_list_foreach (selection, open_one_in_new_window, view);
1287 	}
1288 
1289 	nemo_file_list_free (selection);
1290 }
1291 
1292 static void
action_open_new_tab_callback(GtkAction * action,gpointer callback_data)1293 action_open_new_tab_callback (GtkAction *action,
1294 			      gpointer callback_data)
1295 {
1296 	NemoView *view;
1297 	GList *selection;
1298 	GtkWindow *window;
1299 
1300 	view = NEMO_VIEW (callback_data);
1301 	selection = nemo_view_get_selection (view);
1302 
1303 	window = nemo_view_get_containing_window (view);
1304 
1305 	if (nemo_view_confirm_multiple (window, g_list_length (selection), TRUE)) {
1306 		nemo_view_activate_files (view,
1307 					      selection,
1308 					      NEMO_WINDOW_OPEN_FLAG_NEW_TAB,
1309 					      FALSE);
1310 	}
1311 
1312 	nemo_file_list_free (selection);
1313 }
1314 
1315 static void
app_chooser_dialog_response_cb(GtkDialog * dialog,gint response_id,gpointer user_data)1316 app_chooser_dialog_response_cb (GtkDialog *dialog,
1317 				gint response_id,
1318 				gpointer user_data)
1319 {
1320 	GtkWindow *parent_window;
1321 	NemoFile *file;
1322 	GAppInfo *info;
1323 	GList files;
1324 
1325 	parent_window = user_data;
1326 
1327 	if (response_id != GTK_RESPONSE_OK) {
1328 		gtk_widget_destroy (GTK_WIDGET (dialog));
1329 		return;
1330 	}
1331 
1332     GtkWidget *content = gtk_dialog_get_content_area (dialog);
1333     GList *children = gtk_container_get_children (GTK_CONTAINER (content));
1334 
1335     NemoMimeApplicationChooser *chooser = children->data;
1336 
1337     g_list_free (children);
1338 
1339 	info = nemo_mime_application_chooser_get_info (chooser);
1340 	file = nemo_file_get_by_uri (nemo_mime_application_chooser_get_uri (chooser));
1341 
1342 	g_signal_emit_by_name (nemo_signaller_get_current (), "mime_data_changed");
1343 
1344 	files.next = NULL;
1345 	files.prev = NULL;
1346 	files.data = file;
1347 	nemo_launch_application (info, &files, parent_window);
1348 
1349 	gtk_widget_destroy (GTK_WIDGET (dialog));
1350 	g_object_unref (info);
1351 }
1352 
1353 static void
choose_program(NemoView * view,NemoFile * file)1354 choose_program (NemoView *view,
1355 		NemoFile *file)
1356 {
1357 	GtkWidget *dialog;
1358     GtkWidget *ok_button;
1359 
1360     char *mime_type;
1361     char *uri = NULL;
1362     GList *uris = NULL;
1363 
1364 	g_assert (NEMO_IS_VIEW (view));
1365 	g_assert (NEMO_IS_FILE (file));
1366 
1367     mime_type = nemo_file_get_mime_type (file);
1368     uri = nemo_file_get_uri (file);
1369 
1370     dialog = gtk_dialog_new_with_buttons (_("Open with"),
1371                           nemo_view_get_containing_window (view),
1372                           GTK_DIALOG_DESTROY_WITH_PARENT,
1373                           GTK_STOCK_CANCEL,
1374                           GTK_RESPONSE_CANCEL,
1375                           NULL);
1376     ok_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
1377                                        GTK_STOCK_OK,
1378                                        GTK_RESPONSE_OK);
1379 
1380     gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
1381 
1382     GtkWidget *chooser = nemo_mime_application_chooser_new (uri, uris, mime_type, ok_button);
1383 
1384     GtkWidget *content = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
1385 
1386     gtk_box_pack_start (GTK_BOX (content), chooser, TRUE, TRUE, 0);
1387 
1388     gtk_widget_show_all (dialog);
1389 
1390 	g_signal_connect_object (dialog, "response",
1391 				 G_CALLBACK (app_chooser_dialog_response_cb),
1392 				 nemo_view_get_containing_window (view), 0);
1393 }
1394 
1395 static void
open_with_other_program(NemoView * view)1396 open_with_other_program (NemoView *view)
1397 {
1398         GList *selection;
1399 
1400 	g_assert (NEMO_IS_VIEW (view));
1401 
1402        	selection = nemo_view_get_selection (view);
1403 
1404 	if (selection_contains_one_item_in_menu_callback (view, selection)) {
1405 		choose_program (view, NEMO_FILE (selection->data));
1406 	}
1407 
1408 	nemo_file_list_free (selection);
1409 }
1410 
1411 static void
action_other_application_callback(GtkAction * action,gpointer callback_data)1412 action_other_application_callback (GtkAction *action,
1413 				   gpointer callback_data)
1414 {
1415 	g_assert (NEMO_IS_VIEW (callback_data));
1416 
1417 	open_with_other_program (NEMO_VIEW (callback_data));
1418 }
1419 
1420 static void
trash_or_delete_selected_files(NemoView * view)1421 trash_or_delete_selected_files (NemoView *view)
1422 {
1423         GList *selection;
1424 
1425 	/* This might be rapidly called multiple times for the same selection
1426 	 * when using keybindings. So we remember if the current selection
1427 	 * was already removed (but the view doesn't know about it yet).
1428 	 */
1429 	if (!view->details->selection_was_removed) {
1430 		selection = nemo_view_get_selection_for_file_transfer (view);
1431 
1432         if (selection == NULL) {
1433             return;
1434         }
1435 
1436 		trash_or_delete_files (nemo_view_get_containing_window (view),
1437 				       selection, TRUE,
1438 				       view);
1439 		nemo_file_list_free (selection);
1440 		view->details->selection_was_removed = TRUE;
1441 	}
1442 }
1443 
1444 static gboolean
real_trash(NemoView * view)1445 real_trash (NemoView *view)
1446 {
1447 	GtkAction *action;
1448 
1449 	action = gtk_action_group_get_action (view->details->dir_action_group,
1450 					      NEMO_ACTION_TRASH);
1451 	if ((gtk_action_get_sensitive (action) && gtk_action_get_visible (action)) ||
1452         (showing_favorites_directory (view) || showing_recent_directory (view))) {
1453 		trash_or_delete_selected_files (view);
1454 		return TRUE;
1455 	}
1456 	return FALSE;
1457 }
1458 
1459 static void
action_trash_callback(GtkAction * action,gpointer callback_data)1460 action_trash_callback (GtkAction *action,
1461 		       gpointer callback_data)
1462 {
1463         trash_or_delete_selected_files (NEMO_VIEW (callback_data));
1464 }
1465 
1466 static void
delete_selected_files(NemoView * view)1467 delete_selected_files (NemoView *view)
1468 {
1469         GList *selection;
1470 	GList *node;
1471 	GList *locations;
1472 
1473 	selection = nemo_view_get_selection_for_file_transfer (view);
1474 	if (selection == NULL) {
1475 		return;
1476 	}
1477 
1478 	locations = NULL;
1479 	for (node = selection; node != NULL; node = node->next) {
1480 		locations = g_list_prepend (locations,
1481 					    nemo_file_get_location ((NemoFile *) node->data));
1482 	}
1483 	locations = g_list_reverse (locations);
1484 
1485 	nemo_file_operations_delete (locations, nemo_view_get_containing_window (view), NULL, NULL);
1486 
1487 	g_list_free_full (locations, g_object_unref);
1488         nemo_file_list_free (selection);
1489 }
1490 
1491 static void
action_delete_callback(GtkAction * action,gpointer callback_data)1492 action_delete_callback (GtkAction *action,
1493 			gpointer callback_data)
1494 {
1495         delete_selected_files (NEMO_VIEW (callback_data));
1496 }
1497 
1498 static void
action_restore_from_trash_callback(GtkAction * action,gpointer callback_data)1499 action_restore_from_trash_callback (GtkAction *action,
1500 				    gpointer callback_data)
1501 {
1502 	NemoView *view;
1503 	GList *selection;
1504 
1505 	view = NEMO_VIEW (callback_data);
1506 
1507 	selection = nemo_view_get_selection_for_file_transfer (view);
1508 	nemo_restore_files_from_trash (selection,
1509 					   nemo_view_get_containing_window (view));
1510 
1511 	nemo_file_list_free (selection);
1512 
1513 }
1514 
1515 static gboolean
real_delete(NemoView * view)1516 real_delete (NemoView *view)
1517 {
1518 	GtkAction *action;
1519 
1520 	action = gtk_action_group_get_action (view->details->dir_action_group,
1521 					      NEMO_ACTION_DELETE);
1522 	if (gtk_action_get_sensitive (action) &&
1523 	    gtk_action_get_visible (action)) {
1524 		delete_selected_files (view);
1525 		return TRUE;
1526 	}
1527 	return FALSE;
1528 }
1529 
1530 static void
action_duplicate_callback(GtkAction * action,gpointer callback_data)1531 action_duplicate_callback (GtkAction *action,
1532 			   gpointer callback_data)
1533 {
1534         NemoView *view;
1535         GList *selection;
1536         GArray *selected_item_locations;
1537 
1538         view = NEMO_VIEW (callback_data);
1539 	selection = nemo_view_get_selection_for_file_transfer (view);
1540 	if (selection_not_empty_in_menu_callback (view, selection)) {
1541 		/* FIXME bugzilla.gnome.org 45061:
1542 		 * should change things here so that we use a get_icon_locations (view, selection).
1543 		 * Not a problem in this case but in other places the selection may change by
1544 		 * the time we go and retrieve the icon positions, relying on the selection
1545 		 * staying intact to ensure the right sequence and count of positions is fragile.
1546 		 */
1547 		selected_item_locations = nemo_view_get_selected_icon_locations (view);
1548 	        nemo_view_duplicate_selection (view, selection, selected_item_locations);
1549 	        g_array_free (selected_item_locations, TRUE);
1550 	}
1551 
1552         nemo_file_list_free (selection);
1553 }
1554 
1555 static void
action_create_link_callback(GtkAction * action,gpointer callback_data)1556 action_create_link_callback (GtkAction *action,
1557 			     gpointer callback_data)
1558 {
1559         NemoView *view;
1560         GList *selection;
1561         GArray *selected_item_locations;
1562 
1563         g_assert (NEMO_IS_VIEW (callback_data));
1564 
1565         view = NEMO_VIEW (callback_data);
1566 	selection = nemo_view_get_selection (view);
1567 	if (selection_not_empty_in_menu_callback (view, selection)) {
1568 		selected_item_locations = nemo_view_get_selected_icon_locations (view);
1569 	        nemo_view_create_links_for_files (view, selection, selected_item_locations);
1570 	        g_array_free (selected_item_locations, TRUE);
1571 	}
1572 
1573         nemo_file_list_free (selection);
1574 }
1575 
1576 static void
action_pin_unpin_file_callback(GtkAction * action,gpointer callback_data)1577 action_pin_unpin_file_callback (GtkAction *action,
1578                                 gpointer   callback_data)
1579 {
1580     NemoView *view;
1581     GList *selection;
1582     gboolean to_pin;
1583 
1584     g_assert (NEMO_IS_VIEW (callback_data));
1585 
1586     view = NEMO_VIEW (callback_data);
1587 
1588     selection = nemo_view_get_selection (view);
1589 
1590     if (g_list_length (selection) < 1) {
1591         g_warning ("No selection to pin - why?");
1592         return;
1593     }
1594 
1595     /* Apply pinning according to the current state of the first
1596      * selected file. */
1597     to_pin = !nemo_file_get_pinning (NEMO_FILE (selection->data));
1598 
1599     if (selection_not_empty_in_menu_callback (view, selection)) {
1600         NemoFile *file;
1601         GList *iter;
1602 
1603         for (iter = selection; iter != NULL; iter = iter->next) {
1604             file = NEMO_FILE (iter->data);
1605 
1606             nemo_file_set_pinning (file, to_pin);
1607         }
1608     }
1609 
1610     nemo_file_list_free (selection);
1611 }
1612 
1613 static void
action_favorite_unfavorite_file_callback(GtkAction * action,gpointer callback_data)1614 action_favorite_unfavorite_file_callback (GtkAction *action,
1615                                           gpointer   callback_data)
1616 {
1617     NemoView *view;
1618     GList *selection;
1619     gboolean to_favorite;
1620 
1621     g_assert (NEMO_IS_VIEW (callback_data));
1622 
1623     view = NEMO_VIEW (callback_data);
1624 
1625     selection = nemo_view_get_selection (view);
1626 
1627     if (g_list_length (selection) < 1) {
1628         g_warning ("Favorites - no selection - why?");
1629         return;
1630     }
1631 
1632     /* Apply favorite according to the current state of the first
1633      * selected file. */
1634     to_favorite = !nemo_file_get_is_favorite (NEMO_FILE (selection->data));
1635 
1636     if (selection_not_empty_in_menu_callback (view, selection)) {
1637         NemoFile *file;
1638         GList *iter;
1639 
1640         for (iter = selection; iter != NULL; iter = iter->next) {
1641             file = NEMO_FILE (iter->data);
1642 
1643             nemo_file_set_is_favorite (file, to_favorite);
1644         }
1645     }
1646 
1647     nemo_file_list_free (selection);
1648 }
1649 
1650 static void
action_select_all_callback(GtkAction * action,gpointer callback_data)1651 action_select_all_callback (GtkAction *action,
1652 			    gpointer callback_data)
1653 {
1654 	g_assert (NEMO_IS_VIEW (callback_data));
1655 
1656 	nemo_view_select_all (callback_data);
1657 }
1658 
1659 static void
action_invert_selection_callback(GtkAction * action,gpointer callback_data)1660 action_invert_selection_callback (GtkAction *action,
1661 				  gpointer callback_data)
1662 {
1663 	g_assert (NEMO_IS_VIEW (callback_data));
1664 
1665 	nemo_view_invert_selection (callback_data);
1666 }
1667 
1668 static void
pattern_select_response_cb(GtkWidget * dialog,int response,gpointer user_data)1669 pattern_select_response_cb (GtkWidget *dialog, int response, gpointer user_data)
1670 {
1671 	NemoView *view;
1672 	NemoDirectory *directory;
1673 	GtkWidget *entry;
1674 	GList *selection;
1675 	GError *error;
1676 
1677 	view = NEMO_VIEW (user_data);
1678 
1679 	switch (response) {
1680 	case GTK_RESPONSE_OK :
1681 		entry = g_object_get_data (G_OBJECT (dialog), "entry");
1682 		directory = nemo_view_get_model (view);
1683 		selection = nemo_directory_match_pattern (directory,
1684 							      gtk_entry_get_text (GTK_ENTRY (entry)));
1685 
1686 		if (selection) {
1687 			nemo_view_call_set_selection (view, selection);
1688 			nemo_file_list_free (selection);
1689 
1690 			nemo_view_reveal_selection(view);
1691 		}
1692 		/* fall through */
1693 	case GTK_RESPONSE_NONE :
1694 	case GTK_RESPONSE_DELETE_EVENT :
1695 	case GTK_RESPONSE_CANCEL :
1696 		gtk_widget_destroy (GTK_WIDGET (dialog));
1697 		break;
1698 	case GTK_RESPONSE_HELP :
1699 		error = NULL;
1700 		gtk_show_uri (gtk_window_get_screen (GTK_WINDOW (dialog)),
1701 			      "help:gnome-help/files-select",
1702 			      gtk_get_current_event_time (), &error);
1703 		if (error) {
1704 			eel_show_error_dialog (_("There was an error displaying help."), error->message,
1705 					       GTK_WINDOW (dialog));
1706 			g_error_free (error);
1707 		}
1708 		break;
1709 	default :
1710 		g_assert_not_reached ();
1711 	}
1712 }
1713 
1714 static void
select_pattern(NemoView * view)1715 select_pattern (NemoView *view)
1716 {
1717 	GtkWidget *dialog;
1718 	GtkWidget *label;
1719 	GtkWidget *example;
1720 	GtkWidget *grid;
1721 	GtkWidget *entry;
1722 	char *example_pattern;
1723 
1724 	dialog = gtk_dialog_new_with_buttons (_("Select Items Matching"),
1725 					      nemo_view_get_containing_window (view),
1726 					      GTK_DIALOG_DESTROY_WITH_PARENT,
1727 					      GTK_STOCK_HELP,
1728 					      GTK_RESPONSE_HELP,
1729 					      GTK_STOCK_CANCEL,
1730 					      GTK_RESPONSE_CANCEL,
1731 					      GTK_STOCK_OK,
1732 					      GTK_RESPONSE_OK,
1733 					      NULL);
1734 	gtk_dialog_set_default_response (GTK_DIALOG (dialog),
1735 					 GTK_RESPONSE_OK);
1736 	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
1737 	gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 2);
1738 
1739 	label = gtk_label_new_with_mnemonic (_("_Pattern:"));
1740 	gtk_widget_set_halign (label, GTK_ALIGN_START);
1741 
1742 	example = gtk_label_new (NULL);
1743 	gtk_widget_set_halign (example, GTK_ALIGN_START);
1744 	example_pattern = g_strdup_printf ("<b>%s</b><i>%s</i> ",
1745 					   _("Examples: "),
1746 					   "*.png, file\?\?.txt, pict*.\?\?\?");
1747 	gtk_label_set_markup (GTK_LABEL (example), example_pattern);
1748 	g_free (example_pattern);
1749 
1750 	entry = gtk_entry_new ();
1751 	gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
1752 	gtk_widget_set_hexpand (entry, TRUE);
1753 
1754 	grid = gtk_grid_new ();
1755 	g_object_set (grid,
1756 		      "orientation", GTK_ORIENTATION_VERTICAL,
1757 		      "border-width", 6,
1758 		      "row-spacing", 6,
1759 		      "column-spacing", 12,
1760 		      NULL);
1761 
1762 	gtk_container_add (GTK_CONTAINER (grid), label);
1763 	gtk_grid_attach_next_to (GTK_GRID (grid), entry, label,
1764 				 GTK_POS_RIGHT, 1, 1);
1765 	gtk_grid_attach_next_to (GTK_GRID (grid), example, entry,
1766 				 GTK_POS_BOTTOM, 1, 1);
1767 
1768 	gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
1769 	gtk_widget_show_all (grid);
1770 	gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), grid);
1771 	g_object_set_data (G_OBJECT (dialog), "entry", entry);
1772 	g_signal_connect (dialog, "response",
1773 			  G_CALLBACK (pattern_select_response_cb),
1774 			  view);
1775 	gtk_widget_show_all (dialog);
1776 }
1777 
1778 static void
action_select_pattern_callback(GtkAction * action,gpointer callback_data)1779 action_select_pattern_callback (GtkAction *action,
1780 				gpointer callback_data)
1781 {
1782 	g_assert (NEMO_IS_VIEW (callback_data));
1783 
1784 	select_pattern(callback_data);
1785 }
1786 
1787 static void
action_reset_to_defaults_callback(GtkAction * action,gpointer callback_data)1788 action_reset_to_defaults_callback (GtkAction *action,
1789 				   gpointer callback_data)
1790 {
1791 	g_assert (NEMO_IS_VIEW (callback_data));
1792 
1793 	nemo_view_reset_to_defaults (callback_data);
1794 }
1795 
1796 
1797 static void
hidden_files_mode_changed(NemoWindow * window,gpointer callback_data)1798 hidden_files_mode_changed (NemoWindow *window,
1799 			   gpointer callback_data)
1800 {
1801 	NemoView *directory_view;
1802 
1803 	directory_view = NEMO_VIEW (callback_data);
1804 
1805 	nemo_view_init_show_hidden_files (directory_view);
1806 }
1807 
1808 static void
action_save_search_callback(GtkAction * action,gpointer callback_data)1809 action_save_search_callback (GtkAction *action,
1810 			     gpointer callback_data)
1811 {
1812 	NemoSearchDirectory *search;
1813 	NemoView	*directory_view;
1814 
1815         directory_view = NEMO_VIEW (callback_data);
1816 
1817 	if (directory_view->details->model &&
1818 	    NEMO_IS_SEARCH_DIRECTORY (directory_view->details->model)) {
1819 		search = NEMO_SEARCH_DIRECTORY (directory_view->details->model);
1820 		nemo_search_directory_save_search (search);
1821 
1822 		/* Save search is disabled */
1823 		schedule_update_menus (directory_view);
1824 	}
1825 }
1826 
1827 static void
query_name_entry_changed_cb(GtkWidget * entry,GtkWidget * button)1828 query_name_entry_changed_cb  (GtkWidget *entry, GtkWidget *button)
1829 {
1830 	const char *text;
1831 	gboolean sensitive;
1832 
1833 	text = gtk_entry_get_text (GTK_ENTRY (entry));
1834 
1835 	sensitive = (text != NULL) && (*text != 0);
1836 
1837 	gtk_widget_set_sensitive (button, sensitive);
1838 }
1839 
1840 
1841 static void
action_save_search_as_callback(GtkAction * action,gpointer callback_data)1842 action_save_search_as_callback (GtkAction *action,
1843 				gpointer callback_data)
1844 {
1845 	NemoView	*directory_view;
1846 	NemoSearchDirectory *search;
1847 	GtkWidget *dialog, *grid, *label, *entry, *chooser, *save_button;
1848 	const char *entry_text;
1849 	char *filename, *filename_utf8, *dirname, *path, *uri;
1850 	GFile *location;
1851 
1852         directory_view = NEMO_VIEW (callback_data);
1853 
1854 	if (directory_view->details->model &&
1855 	    NEMO_IS_SEARCH_DIRECTORY (directory_view->details->model)) {
1856 		search = NEMO_SEARCH_DIRECTORY (directory_view->details->model);
1857 
1858 		dialog = gtk_dialog_new_with_buttons (_("Save Search as"),
1859 						      nemo_view_get_containing_window (directory_view),
1860 						      0,
1861 						      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1862 						      NULL);
1863 		save_button = gtk_dialog_add_button (GTK_DIALOG (dialog),
1864 						     GTK_STOCK_SAVE, GTK_RESPONSE_OK);
1865 		gtk_dialog_set_default_response (GTK_DIALOG (dialog),
1866 						 GTK_RESPONSE_OK);
1867 		gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
1868 		gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 2);
1869 		gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
1870 
1871 		grid = gtk_grid_new ();
1872 		g_object_set (grid,
1873 			      "orientation", GTK_ORIENTATION_VERTICAL,
1874 			      "border-width", 5,
1875 			      "row-spacing", 6,
1876 			      "column-spacing", 12,
1877 			      NULL);
1878 		gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), grid, TRUE, TRUE, 0);
1879 		gtk_widget_show (grid);
1880 
1881 		label = gtk_label_new_with_mnemonic (_("Search _name:"));
1882 		gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1883 		gtk_container_add (GTK_CONTAINER (grid), label);
1884 		gtk_widget_show (label);
1885 
1886 		entry = gtk_entry_new ();
1887 		gtk_widget_set_hexpand (entry, TRUE);
1888 		gtk_grid_attach_next_to (GTK_GRID (grid), entry, label,
1889 					 GTK_POS_RIGHT, 1, 1);
1890 		gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
1891 		gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
1892 
1893 		gtk_widget_set_sensitive (save_button, FALSE);
1894 		g_signal_connect (entry, "changed",
1895 				  G_CALLBACK (query_name_entry_changed_cb), save_button);
1896 
1897 		gtk_widget_show (entry);
1898 		label = gtk_label_new_with_mnemonic (_("_Folder:"));
1899 		gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.5);
1900 		gtk_container_add (GTK_CONTAINER (grid), label);
1901 		gtk_widget_show (label);
1902 
1903 		chooser = gtk_file_chooser_button_new (_("Select Folder to Save Search In"),
1904 						       GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
1905 		gtk_widget_set_hexpand (chooser, TRUE);
1906 		gtk_grid_attach_next_to (GTK_GRID (grid), chooser, label,
1907 					 GTK_POS_RIGHT, 1, 1);
1908 		gtk_label_set_mnemonic_widget (GTK_LABEL (label), chooser);
1909 		gtk_widget_show (chooser);
1910 
1911 		gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (chooser), TRUE);
1912 
1913 		gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (chooser),
1914 						     g_get_home_dir ());
1915 
1916 		if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
1917 			entry_text = gtk_entry_get_text (GTK_ENTRY (entry));
1918 			if (g_str_has_suffix (entry_text, NEMO_SAVED_SEARCH_EXTENSION)) {
1919 				filename_utf8 = g_strdup (entry_text);
1920 			} else {
1921 				filename_utf8 = g_strconcat (entry_text, NEMO_SAVED_SEARCH_EXTENSION, NULL);
1922 			}
1923 
1924 			filename = g_filename_from_utf8 (filename_utf8, -1, NULL, NULL, NULL);
1925 			g_free (filename_utf8);
1926 
1927 			dirname = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));
1928 
1929 			path = g_build_filename (dirname, filename, NULL);
1930 			g_free (filename);
1931 			g_free (dirname);
1932 
1933 			uri = g_filename_to_uri (path, NULL, NULL);
1934 			g_free (path);
1935 
1936 			nemo_search_directory_save_to_file (search, uri);
1937 			location = g_file_new_for_uri (uri);
1938 			nemo_file_changes_queue_file_added (location);
1939 			g_object_unref (location);
1940 			nemo_file_changes_consume_changes (TRUE);
1941 			g_free (uri);
1942 		}
1943 
1944 		gtk_widget_destroy (dialog);
1945 	}
1946 }
1947 
1948 
1949 static void
action_empty_trash_callback(GtkAction * action,gpointer callback_data)1950 action_empty_trash_callback (GtkAction *action,
1951 			     gpointer callback_data)
1952 {
1953         g_assert (NEMO_IS_VIEW (callback_data));
1954 
1955 	nemo_file_operations_empty_trash (GTK_WIDGET (callback_data));
1956 }
1957 
1958 typedef struct {
1959 	NemoView *view;
1960 	NemoFile *new_file;
1961 } RenameData;
1962 
1963 static gboolean
delayed_rename_file_hack_callback(RenameData * data)1964 delayed_rename_file_hack_callback (RenameData *data)
1965 {
1966 	NemoView *view;
1967 	NemoFile *new_file;
1968 
1969 	view = data->view;
1970 	new_file = data->new_file;
1971 
1972 	if (view->details->window != NULL &&
1973 	    view->details->active) {
1974 		NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->start_renaming_file (view, new_file, FALSE);
1975 		nemo_view_reveal_selection (view);
1976 	}
1977 
1978     view->details->delayed_rename_file_id = 0;
1979 	return FALSE;
1980 }
1981 
1982 static void
delayed_rename_file_hack_removed(RenameData * data)1983 delayed_rename_file_hack_removed (RenameData *data)
1984 {
1985 	g_object_unref (data->view);
1986 	nemo_file_unref (data->new_file);
1987 	g_free (data);
1988 }
1989 
1990 
1991 static void
rename_file(NemoView * view,NemoFile * new_file)1992 rename_file (NemoView *view, NemoFile *new_file)
1993 {
1994 	RenameData *data;
1995 
1996 	/* HACK!!!!
1997 	   This is a work around bug in listview. After the rename is
1998 	   enabled we will get file changes due to info about the new
1999 	   file being read, which will cause the model to change. When
2000 	   the model changes GtkTreeView clears the editing. This hack just
2001 	   delays editing for some time to try to avoid this problem.
2002 	   A major problem is that the selection of the row causes us
2003 	   to load the slow mimetype for the file, which leads to a
2004 	   file_changed. So, before we delay we select the row.
2005 	*/
2006 	if (NEMO_IS_LIST_VIEW (view)) {
2007 		nemo_view_select_file (view, new_file);
2008 
2009 		data = g_new (RenameData, 1);
2010 		data->view = g_object_ref (view);
2011 		data->new_file = nemo_file_ref (new_file);
2012 		if (view->details->delayed_rename_file_id != 0) {
2013 			g_source_remove (view->details->delayed_rename_file_id);
2014 		}
2015 		view->details->delayed_rename_file_id =
2016 			g_timeout_add_full (G_PRIORITY_DEFAULT,
2017 					    100, (GSourceFunc)delayed_rename_file_hack_callback,
2018 					    data, (GDestroyNotify) delayed_rename_file_hack_removed);
2019 
2020 		return;
2021 	}
2022 
2023 	/* no need to select because start_renaming_file selects
2024 	 * nemo_view_select_file (view, new_file);
2025 	 */
2026 	NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->start_renaming_file (view, new_file, FALSE);
2027 	nemo_view_reveal_selection (view);
2028 }
2029 
2030 static void
reveal_newly_added_folder(NemoView * view,NemoFile * new_file,NemoDirectory * directory,GFile * target_location)2031 reveal_newly_added_folder (NemoView *view, NemoFile *new_file,
2032 			   NemoDirectory *directory, GFile *target_location)
2033 {
2034 	GFile *location;
2035 
2036 	location = nemo_file_get_location (new_file);
2037 	if (g_file_equal (location, target_location)) {
2038 		g_signal_handlers_disconnect_by_func (view,
2039 						      G_CALLBACK (reveal_newly_added_folder),
2040 						      (void *) target_location);
2041 		rename_file (view, new_file);
2042 	}
2043 	g_object_unref (location);
2044 }
2045 
2046 typedef struct {
2047 	NemoView *directory_view;
2048 	GHashTable *added_locations;
2049 } NewFolderData;
2050 
2051 
2052 static void
track_newly_added_locations(NemoView * view,NemoFile * new_file,NemoDirectory * directory,gpointer user_data)2053 track_newly_added_locations (NemoView *view, NemoFile *new_file,
2054 			     NemoDirectory *directory, gpointer user_data)
2055 {
2056 	NewFolderData *data;
2057 
2058 	data = user_data;
2059 
2060 	g_hash_table_insert (data->added_locations, nemo_file_get_location (new_file), NULL);
2061 }
2062 
2063 static void
new_folder_done(GFile * new_folder,gboolean success,gpointer user_data)2064 new_folder_done (GFile *new_folder,
2065 		 gboolean success,
2066 		 gpointer user_data)
2067 {
2068 	NemoView *directory_view;
2069 	NemoFile *file;
2070 	char screen_string[32];
2071 	GdkScreen *screen;
2072 	NewFolderData *data;
2073 
2074 	data = (NewFolderData *)user_data;
2075 
2076 	directory_view = data->directory_view;
2077 
2078 	if (directory_view == NULL) {
2079 		goto fail;
2080 	}
2081 
2082 	g_signal_handlers_disconnect_by_func (directory_view,
2083 					      G_CALLBACK (track_newly_added_locations),
2084 					      (void *) data);
2085 
2086 	if (new_folder == NULL) {
2087 		goto fail;
2088 	}
2089 
2090 	screen = gtk_widget_get_screen (GTK_WIDGET (directory_view));
2091 	g_snprintf (screen_string, sizeof (screen_string), "%d", gdk_screen_get_number (screen));
2092 
2093 
2094 	file = nemo_file_get (new_folder);
2095 
2096 	if (g_hash_table_lookup_extended (data->added_locations, new_folder, NULL, NULL)) {
2097 		/* The file was already added */
2098 		rename_file (directory_view, file);
2099 	} else {
2100 		/* We need to run after the default handler adds the folder we want to
2101 		 * operate on. The ADD_FILE signal is registered as G_SIGNAL_RUN_LAST, so we
2102 		 * must use connect_after.
2103 		 */
2104 		g_signal_connect_data (directory_view,
2105 				       "add_file",
2106 				       G_CALLBACK (reveal_newly_added_folder),
2107 				       g_object_ref (new_folder),
2108 				       (GClosureNotify)g_object_unref,
2109 				       G_CONNECT_AFTER);
2110 	}
2111 	nemo_file_unref (file);
2112 
2113  fail:
2114 	g_hash_table_destroy (data->added_locations);
2115 
2116 	if (data->directory_view != NULL) {
2117 		g_object_remove_weak_pointer (G_OBJECT (data->directory_view),
2118 					      (gpointer *) &data->directory_view);
2119 	}
2120 
2121 	g_free (data);
2122 }
2123 
2124 
2125 static NewFolderData *
new_folder_data_new(NemoView * directory_view)2126 new_folder_data_new (NemoView *directory_view)
2127 {
2128 	NewFolderData *data;
2129 
2130 	data = g_new (NewFolderData, 1);
2131 	data->directory_view = directory_view;
2132 	data->added_locations = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal,
2133 						       g_object_unref, NULL);
2134 	g_object_add_weak_pointer (G_OBJECT (data->directory_view),
2135 				   (gpointer *) &data->directory_view);
2136 
2137 	return data;
2138 }
2139 
2140 static GdkPoint *
context_menu_to_file_operation_position(NemoView * view)2141 context_menu_to_file_operation_position (NemoView *view)
2142 {
2143 	g_return_val_if_fail (NEMO_IS_VIEW (view), NULL);
2144 
2145 	if (nemo_view_using_manual_layout (view)
2146 	    && view->details->context_menu_position.x >= 0
2147 	    && view->details->context_menu_position.y >= 0) {
2148 		NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->widget_to_file_operation_position
2149 			(view, &view->details->context_menu_position);
2150 		return &view->details->context_menu_position;
2151 	} else {
2152 		return NULL;
2153 	}
2154 }
2155 
2156 void
nemo_view_new_folder(NemoView * view)2157 nemo_view_new_folder (NemoView *view)
2158 {
2159 	char *parent_uri;
2160 	NewFolderData *data;
2161 	GdkPoint *pos;
2162 
2163 	data = new_folder_data_new (view);
2164 
2165 	g_signal_connect_data (view,
2166 			       "add_file",
2167 			       G_CALLBACK (track_newly_added_locations),
2168 			       data,
2169 			       (GClosureNotify)NULL,
2170 			       G_CONNECT_AFTER);
2171 
2172 	pos = context_menu_to_file_operation_position (view);
2173 
2174 	parent_uri = nemo_view_get_backing_uri (view);
2175 	nemo_file_operations_new_folder (GTK_WIDGET (view),
2176 					     pos, parent_uri,
2177 					     new_folder_done, data);
2178 
2179 	g_free (parent_uri);
2180 }
2181 
2182 static NewFolderData *
setup_new_folder_data(NemoView * directory_view)2183 setup_new_folder_data (NemoView *directory_view)
2184 {
2185 	NewFolderData *data;
2186 
2187 	data = new_folder_data_new (directory_view);
2188 
2189 	g_signal_connect_data (directory_view,
2190 			       "add_file",
2191 			       G_CALLBACK (track_newly_added_locations),
2192 			       data,
2193 			       (GClosureNotify)NULL,
2194 			       G_CONNECT_AFTER);
2195 
2196 	return data;
2197 }
2198 
2199 void
nemo_view_new_file_with_initial_contents(NemoView * view,const char * parent_uri,const char * filename,const char * initial_contents,int length,GdkPoint * pos)2200 nemo_view_new_file_with_initial_contents (NemoView *view,
2201 					      const char *parent_uri,
2202 					      const char *filename,
2203 					      const char *initial_contents,
2204 					      int length,
2205 					      GdkPoint *pos)
2206 {
2207 	NewFolderData *data;
2208 
2209 	g_assert (parent_uri != NULL);
2210 
2211 	data = setup_new_folder_data (view);
2212 
2213 	if (pos == NULL) {
2214 		pos = context_menu_to_file_operation_position (view);
2215 	}
2216 
2217 	nemo_file_operations_new_file (GTK_WIDGET (view),
2218 					   pos, parent_uri, filename,
2219 					   initial_contents, length,
2220 					   new_folder_done, data);
2221 }
2222 
2223 static void
nemo_view_new_file(NemoView * directory_view,const char * parent_uri,NemoFile * source)2224 nemo_view_new_file (NemoView *directory_view,
2225 			const char *parent_uri,
2226 			NemoFile *source)
2227 {
2228 	GdkPoint *pos;
2229 	NewFolderData *data;
2230 	char *source_uri;
2231 	char *container_uri;
2232 
2233 	container_uri = NULL;
2234 	if (parent_uri == NULL) {
2235 		container_uri = nemo_view_get_backing_uri (directory_view);
2236 		g_assert (container_uri != NULL);
2237 	}
2238 
2239 	if (source == NULL) {
2240 		nemo_view_new_file_with_initial_contents (directory_view,
2241 							      parent_uri != NULL ? parent_uri : container_uri,
2242 							      NULL,
2243 							      NULL,
2244 							      0,
2245 							      NULL);
2246 		g_free (container_uri);
2247 		return;
2248 	}
2249 
2250 	g_return_if_fail (nemo_file_is_local (source));
2251 
2252 	pos = context_menu_to_file_operation_position (directory_view);
2253 
2254 	data = setup_new_folder_data (directory_view);
2255 
2256 	source_uri = nemo_file_get_uri (source);
2257 
2258 	nemo_file_operations_new_file_from_template (GTK_WIDGET (directory_view),
2259 							 pos,
2260 							 parent_uri != NULL ? parent_uri : container_uri,
2261 							 NULL,
2262 							 source_uri,
2263 							 new_folder_done, data);
2264 
2265 	g_free (source_uri);
2266 	g_free (container_uri);
2267 }
2268 
2269 static void
action_new_folder_callback(GtkAction * action,gpointer callback_data)2270 action_new_folder_callback (GtkAction *action,
2271 			    gpointer callback_data)
2272 {
2273         g_assert (NEMO_IS_VIEW (callback_data));
2274 
2275 	nemo_view_new_folder (NEMO_VIEW (callback_data));
2276 }
2277 
2278 static void
action_new_empty_file_callback(GtkAction * action,gpointer callback_data)2279 action_new_empty_file_callback (GtkAction *action,
2280 				gpointer callback_data)
2281 {
2282         g_assert (NEMO_IS_VIEW (callback_data));
2283 
2284 	nemo_view_new_file (NEMO_VIEW (callback_data), NULL, NULL);
2285 }
2286 
2287 static void
action_properties_callback(GtkAction * action,gpointer callback_data)2288 action_properties_callback (GtkAction *action,
2289 			    gpointer callback_data)
2290 {
2291         NemoView *view;
2292         GList *selection;
2293 	GList *files;
2294 
2295         g_assert (NEMO_IS_VIEW (callback_data));
2296 
2297         view = NEMO_VIEW (callback_data);
2298 	selection = nemo_view_get_selection (view);
2299 	if (g_list_length (selection) == 0) {
2300 		if (view->details->directory_as_file != NULL) {
2301 			files = g_list_append (NULL, nemo_file_ref (view->details->directory_as_file));
2302 
2303 			nemo_properties_window_present (files, GTK_WIDGET (view), NULL);
2304 
2305 			nemo_file_list_free (files);
2306 		}
2307 	} else {
2308 		nemo_properties_window_present (selection, GTK_WIDGET (view), NULL);
2309 	}
2310         nemo_file_list_free (selection);
2311 }
2312 
2313 static void
action_location_properties_callback(GtkAction * action,gpointer callback_data)2314 action_location_properties_callback (GtkAction *action,
2315 				     gpointer   callback_data)
2316 {
2317 	NemoView *view;
2318 	GList           *files;
2319 
2320 	g_assert (NEMO_IS_VIEW (callback_data));
2321 
2322 	view = NEMO_VIEW (callback_data);
2323 	g_assert (NEMO_IS_FILE (view->details->location_popup_directory_as_file));
2324 
2325 	files = g_list_append (NULL, nemo_file_ref (view->details->location_popup_directory_as_file));
2326 
2327 	nemo_properties_window_present (files, GTK_WIDGET (view), NULL);
2328 
2329 	nemo_file_list_free (files);
2330 }
2331 
2332 static gboolean
all_files_in_trash(GList * files)2333 all_files_in_trash (GList *files)
2334 {
2335 	GList *node;
2336 
2337 	/* Result is ambiguous if called on NULL, so disallow. */
2338 	g_return_val_if_fail (files != NULL, FALSE);
2339 
2340 	for (node = files; node != NULL; node = node->next) {
2341 		if (!nemo_file_is_in_trash (NEMO_FILE (node->data))) {
2342 			return FALSE;
2343 		}
2344 	}
2345 
2346 	return TRUE;
2347 }
2348 
2349 static gboolean
all_selected_items_in_trash(NemoView * view,GList * selection)2350 all_selected_items_in_trash (NemoView *view, GList *selection)
2351 {
2352 	gboolean result;
2353 
2354 	/* If the contents share a parent directory, we need only
2355 	 * check that parent directory. Otherwise we have to inspect
2356 	 * each selected item.
2357 	 */
2358 
2359 	result = (selection == NULL) ? FALSE : all_files_in_trash (selection);
2360 
2361 	return result;
2362 }
2363 
2364 static void
click_policy_changed_callback(gpointer callback_data)2365 click_policy_changed_callback (gpointer callback_data)
2366 {
2367 	NemoView *view;
2368 
2369 	view = NEMO_VIEW (callback_data);
2370 
2371 	NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->click_policy_changed (view);
2372 }
2373 
2374 static void
click_to_rename_changed_callback(gpointer callback_data)2375 click_to_rename_changed_callback (gpointer callback_data)
2376 {
2377     NemoView *view;
2378 
2379     view = NEMO_VIEW (callback_data);
2380 
2381     NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->click_to_rename_mode_changed (view);
2382 }
2383 
2384 static void
nemo_to_menu_preferences_changed_callback(NemoView * view)2385 nemo_to_menu_preferences_changed_callback (NemoView *view)
2386 {
2387     view->details->showing_bookmarks_in_to_menus = g_settings_get_boolean (nemo_preferences,
2388                                                                            NEMO_PREFERENCES_SHOW_BOOKMARKS_IN_TO_MENUS);
2389     view->details->showing_places_in_to_menus = g_settings_get_boolean (nemo_preferences,
2390                                                                         NEMO_PREFERENCES_SHOW_PLACES_IN_TO_MENUS);
2391 }
2392 
2393 gboolean
nemo_view_should_sort_directories_first(NemoView * view)2394 nemo_view_should_sort_directories_first (NemoView *view)
2395 {
2396 	return view->details->sort_directories_first;
2397 }
2398 
2399 static void
sort_directories_first_changed_callback(gpointer callback_data)2400 sort_directories_first_changed_callback (gpointer callback_data)
2401 {
2402 	NemoView *view;
2403 	gboolean preference_value;
2404 
2405 	view = NEMO_VIEW (callback_data);
2406 
2407 	preference_value =
2408 		g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_SORT_DIRECTORIES_FIRST);
2409 
2410 	if (preference_value != view->details->sort_directories_first) {
2411 		view->details->sort_directories_first = preference_value;
2412 		return NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->sort_directories_first_changed (view);
2413 	}
2414 }
2415 
2416 static void
swap_delete_keybinding_changed_callback(gpointer callback_data)2417 swap_delete_keybinding_changed_callback (gpointer callback_data)
2418 {
2419     GtkBindingSet *binding_set = gtk_binding_set_find ("NemoView");
2420 
2421     gboolean swap_keys = g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_SWAP_TRASH_DELETE);
2422 
2423     gtk_binding_entry_remove (binding_set, GDK_KEY_Delete, 0);
2424     gtk_binding_entry_remove (binding_set, GDK_KEY_KP_Delete, 0);
2425     gtk_binding_entry_remove (binding_set, GDK_KEY_KP_Delete, GDK_SHIFT_MASK);
2426     gtk_binding_entry_remove (binding_set, GDK_KEY_Delete, GDK_SHIFT_MASK);
2427 
2428     if (swap_keys) {
2429         gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, 0,
2430                           "delete", 0);
2431         gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, 0,
2432                           "delete", 0);
2433         gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, GDK_SHIFT_MASK,
2434                           "trash", 0);
2435         gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, GDK_SHIFT_MASK,
2436                           "trash", 0);
2437     } else {
2438         gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, 0,
2439                           "trash", 0);
2440         gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, 0,
2441                           "trash", 0);
2442         gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, GDK_SHIFT_MASK,
2443                           "delete", 0);
2444         gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, GDK_SHIFT_MASK,
2445                           "delete", 0);
2446     }
2447 }
2448 
2449 static gboolean
set_up_scripts_directory_global(void)2450 set_up_scripts_directory_global (void)
2451 {
2452 	char *scripts_directory_path;
2453 
2454 	if (scripts_directory_uri != NULL) {
2455 		return TRUE;
2456 	}
2457 
2458 	scripts_directory_path = nemo_get_scripts_directory_path ();
2459 
2460 	if (g_mkdir_with_parents (scripts_directory_path, 0755) == 0) {
2461 		scripts_directory_uri = g_filename_to_uri (scripts_directory_path, NULL, NULL);
2462 		scripts_directory_uri_length = strlen (scripts_directory_uri);
2463 	}
2464 
2465 	g_free (scripts_directory_path);
2466 
2467 	return (scripts_directory_uri != NULL) ? TRUE : FALSE;
2468 }
2469 
2470 static void
scripts_added_or_changed_callback(NemoDirectory * directory,GList * files,gpointer callback_data)2471 scripts_added_or_changed_callback (NemoDirectory *directory,
2472 				   GList *files,
2473 				   gpointer callback_data)
2474 {
2475 	NemoView *view;
2476 
2477 	view = NEMO_VIEW (callback_data);
2478 
2479 	view->details->scripts_invalid = TRUE;
2480 	if (view->details->active) {
2481 		schedule_update_menus (view);
2482 	}
2483 }
2484 
2485 static void
templates_added_or_changed_callback(NemoDirectory * directory,GList * files,gpointer callback_data)2486 templates_added_or_changed_callback (NemoDirectory *directory,
2487 				     GList *files,
2488 				     gpointer callback_data)
2489 {
2490 	NemoView *view;
2491 
2492 	view = NEMO_VIEW (callback_data);
2493 
2494 	view->details->templates_invalid = TRUE;
2495 	if (view->details->active) {
2496 		schedule_update_menus (view);
2497 	}
2498 }
2499 
2500 static void
actions_added_or_changed_callback(NemoView * view)2501 actions_added_or_changed_callback (NemoView *view)
2502 {
2503     view->details->actions_invalid = TRUE;
2504     if (view->details->active) {
2505         schedule_update_menus (view);
2506     }
2507 }
2508 
2509 static void
add_directory_to_directory_list(NemoView * view,NemoDirectory * directory,GList ** directory_list,GCallback changed_callback)2510 add_directory_to_directory_list (NemoView *view,
2511 				 NemoDirectory *directory,
2512 				 GList **directory_list,
2513 				 GCallback changed_callback)
2514 {
2515 	NemoFileAttributes attributes;
2516 
2517 	if (g_list_find (*directory_list, directory) == NULL) {
2518 		nemo_directory_ref (directory);
2519 
2520 		attributes =
2521 			NEMO_FILE_ATTRIBUTES_FOR_ICON |
2522 			NEMO_FILE_ATTRIBUTE_INFO |
2523 			NEMO_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT;
2524 
2525 		nemo_directory_file_monitor_add (directory, directory_list,
2526 						     FALSE, attributes,
2527 						     (NemoDirectoryCallback)changed_callback, view);
2528 
2529 		g_signal_connect_object (directory, "files_added",
2530 					 G_CALLBACK (changed_callback), view, 0);
2531 		g_signal_connect_object (directory, "files_changed",
2532 					 G_CALLBACK (changed_callback), view, 0);
2533 
2534 		*directory_list = g_list_append	(*directory_list, directory);
2535 	}
2536 }
2537 
2538 static void
remove_directory_from_directory_list(NemoView * view,NemoDirectory * directory,GList ** directory_list,GCallback changed_callback)2539 remove_directory_from_directory_list (NemoView *view,
2540 				      NemoDirectory *directory,
2541 				      GList **directory_list,
2542 				      GCallback changed_callback)
2543 {
2544 	*directory_list = g_list_remove	(*directory_list, directory);
2545 
2546 	g_signal_handlers_disconnect_by_func (directory,
2547 					      G_CALLBACK (changed_callback),
2548 					      view);
2549 
2550 	nemo_directory_file_monitor_remove (directory, directory_list);
2551 
2552 	nemo_directory_unref (directory);
2553 }
2554 
2555 static void
add_directory_to_scripts_directory_list(NemoView * view,NemoDirectory * directory)2556 add_directory_to_scripts_directory_list (NemoView *view,
2557 					 NemoDirectory *directory)
2558 {
2559 	add_directory_to_directory_list (view, directory,
2560 					 &view->details->scripts_directory_list,
2561 					 G_CALLBACK (scripts_added_or_changed_callback));
2562 }
2563 
2564 static void
remove_directory_from_scripts_directory_list(NemoView * view,NemoDirectory * directory)2565 remove_directory_from_scripts_directory_list (NemoView *view,
2566 					      NemoDirectory *directory)
2567 {
2568 	remove_directory_from_directory_list (view, directory,
2569 					      &view->details->scripts_directory_list,
2570 					      G_CALLBACK (scripts_added_or_changed_callback));
2571 }
2572 
2573 static void
add_directory_to_templates_directory_list(NemoView * view,NemoDirectory * directory)2574 add_directory_to_templates_directory_list (NemoView *view,
2575 					   NemoDirectory *directory)
2576 {
2577 	add_directory_to_directory_list (view, directory,
2578 					 &view->details->templates_directory_list,
2579 					 G_CALLBACK (templates_added_or_changed_callback));
2580 }
2581 
2582 static void
remove_directory_from_templates_directory_list(NemoView * view,NemoDirectory * directory)2583 remove_directory_from_templates_directory_list (NemoView *view,
2584 						NemoDirectory *directory)
2585 {
2586 	remove_directory_from_directory_list (view, directory,
2587 					      &view->details->templates_directory_list,
2588 					      G_CALLBACK (templates_added_or_changed_callback));
2589 }
2590 
2591 static void
slot_active(NemoWindowSlot * slot,NemoView * view)2592 slot_active (NemoWindowSlot *slot,
2593 	     NemoView *view)
2594 {
2595 	if (view->details->active) {
2596 		return;
2597 	}
2598 
2599 	view->details->active = TRUE;
2600 
2601 	nemo_view_merge_menus (view);
2602 	schedule_update_menus (view);
2603 }
2604 
2605 static void
slot_inactive(NemoWindowSlot * slot,NemoView * view)2606 slot_inactive (NemoWindowSlot *slot,
2607 	       NemoView *view)
2608 {
2609 	if (!view->details->active) {
2610 		return;
2611 	}
2612 
2613 	view->details->active = FALSE;
2614 
2615 	nemo_view_unmerge_menus (view);
2616 	remove_update_menus_timeout_callback (view);
2617 }
2618 
slot_changed_pane(NemoWindowSlot * slot,NemoView * view)2619 static void slot_changed_pane (NemoWindowSlot *slot,
2620 			       NemoView *view)
2621 {
2622 	g_signal_handlers_disconnect_matched (view->details->window,
2623 					      G_SIGNAL_MATCH_DATA, 0, 0,
2624 					      NULL, NULL, view);
2625 
2626 	view->details->window = nemo_window_slot_get_window (slot);
2627 	schedule_update_menus (view);
2628 
2629 	g_signal_connect_object (view->details->window,
2630 		"hidden-files-mode-changed", G_CALLBACK (hidden_files_mode_changed),
2631 		view, 0);
2632 	hidden_files_mode_changed (view->details->window, view);
2633 }
2634 
2635 static void
plugin_prefs_changed(GSettings * settings,gchar * key,gpointer user_data)2636 plugin_prefs_changed (GSettings *settings, gchar *key, gpointer user_data)
2637 {
2638     scripts_added_or_changed_callback (NULL, NULL, user_data);
2639 }
2640 
2641 void
nemo_view_grab_focus(NemoView * view)2642 nemo_view_grab_focus (NemoView *view)
2643 {
2644 	/* focus the child of the scrolled window if it exists */
2645 	GtkWidget *child;
2646 	child = gtk_bin_get_child (GTK_BIN (view));
2647 	if (child) {
2648 		gtk_widget_grab_focus (GTK_WIDGET (child));
2649 	}
2650 }
2651 
2652 int
nemo_view_get_selection_count(NemoView * view)2653 nemo_view_get_selection_count (NemoView *view)
2654 {
2655     /* FIXME: This could be faster if we special cased it in subclasses */
2656     GList *files;
2657     int len;
2658 
2659     files = nemo_view_get_selection (NEMO_VIEW (view));
2660     len = g_list_length (files);
2661     nemo_file_list_free (files);
2662 
2663     return len;
2664 }
2665 
2666 static void
update_undo_actions(NemoView * view)2667 update_undo_actions (NemoView *view)
2668 {
2669 	NemoFileUndoInfo *info;
2670 	NemoFileUndoManagerState undo_state;
2671 	GtkAction *action;
2672 	const gchar *label, *tooltip;
2673 	gboolean available;
2674 	gboolean undo_active, redo_active;
2675 	gchar *undo_label, *undo_description, *redo_label, *redo_description;
2676 
2677 	undo_label = undo_description = redo_label = redo_description = NULL;
2678 
2679 	undo_active = FALSE;
2680 	redo_active = FALSE;
2681 
2682 	info = nemo_file_undo_manager_get_action ();
2683 	undo_state = nemo_file_undo_manager_get_state ();
2684 
2685 	if (info != NULL &&
2686 	    (undo_state > NEMO_FILE_UNDO_MANAGER_STATE_NONE)) {
2687 		if (undo_state == NEMO_FILE_UNDO_MANAGER_STATE_UNDO) {
2688 			undo_active = TRUE;
2689 		} else {
2690 			redo_active = TRUE;
2691 		}
2692 
2693 		nemo_file_undo_info_get_strings (info,
2694 						     &undo_label, &undo_description,
2695 						     &redo_label, &redo_description);
2696 	}
2697 
2698 	/* Update undo entry */
2699 	action = gtk_action_group_get_action (view->details->dir_action_group,
2700 					      "Undo");
2701 	available = undo_active;
2702 	if (available) {
2703 		label = undo_label;
2704 		tooltip = undo_description;
2705 	} else {
2706 		/* Reset to default info */
2707 		label = _("Undo");
2708 		tooltip = _("Undo last action");
2709 	}
2710 
2711 	g_object_set (action,
2712 		      "label", label,
2713 		      "tooltip", tooltip,
2714 		      NULL);
2715 	gtk_action_set_sensitive (action, available);
2716 
2717 	/* Update redo entry */
2718 	action = gtk_action_group_get_action (view->details->dir_action_group,
2719 					      "Redo");
2720 	available = redo_active;
2721 	if (available) {
2722 		label = redo_label;
2723 		tooltip = redo_description;
2724 	} else {
2725 		/* Reset to default info */
2726 		label = _("Redo");
2727 		tooltip = _("Redo last undone action");
2728 	}
2729 
2730 	g_object_set (action,
2731 		      "label", label,
2732 		      "tooltip", tooltip,
2733 		      NULL);
2734 	gtk_action_set_sensitive (action, available);
2735 
2736 	g_free (undo_label);
2737 	g_free (undo_description);
2738 	g_free (redo_label);
2739 	g_free (redo_description);
2740 }
2741 
2742 static void
undo_manager_changed_cb(NemoFileUndoManager * manager,NemoView * view)2743 undo_manager_changed_cb (NemoFileUndoManager* manager,
2744 			 NemoView *view)
2745 {
2746     if (view->details->dir_action_group == NULL) {
2747         return;
2748     }
2749 
2750 	update_undo_actions (view);
2751 }
2752 
2753 void
nemo_view_set_selection(NemoView * nemo_view,GList * selection)2754 nemo_view_set_selection (NemoView *nemo_view,
2755 			     GList *selection)
2756 {
2757 	NemoView *view;
2758 
2759 	view = NEMO_VIEW (nemo_view);
2760 
2761 	if (!view->details->loading) {
2762 		/* If we aren't still loading, set the selection right now,
2763 		 * and reveal the new selection.
2764 		 */
2765 		view->details->selection_change_is_due_to_shell = TRUE;
2766 		nemo_view_call_set_selection (view, selection);
2767 		view->details->selection_change_is_due_to_shell = FALSE;
2768 		nemo_view_reveal_selection (view);
2769 	} else {
2770 		/* If we are still loading, set the list of pending URIs instead.
2771 		 * done_loading() will eventually select the pending URIs and reveal them.
2772 		 */
2773 		g_list_free_full (view->details->pending_selection, g_object_unref);
2774 		view->details->pending_selection =
2775 			eel_g_object_list_copy (selection);
2776 	}
2777 }
2778 
2779 static char *
get_bulk_rename_tool(void)2780 get_bulk_rename_tool (void)
2781 {
2782 	char *bulk_rename_tool;
2783 	g_settings_get (nemo_preferences, NEMO_PREFERENCES_BULK_RENAME_TOOL, "^ay", &bulk_rename_tool);
2784 	return g_strstrip (bulk_rename_tool);
2785 }
2786 
2787 static gboolean
have_bulk_rename_tool(void)2788 have_bulk_rename_tool (void)
2789 {
2790 	char *bulk_rename_tool;
2791 	gboolean have_tool;
2792 
2793 	bulk_rename_tool = get_bulk_rename_tool ();
2794 	have_tool = ((bulk_rename_tool != NULL) && (*bulk_rename_tool != '\0'));
2795 	g_free (bulk_rename_tool);
2796 	return have_tool;
2797 }
2798 
2799 static void
nemo_view_init(NemoView * view)2800 nemo_view_init (NemoView *view)
2801 {
2802 	AtkObject *atk_object;
2803 	NemoDirectory *scripts_directory;
2804 	NemoDirectory *templates_directory;
2805 	char *templates_uri;
2806 	NemoFileUndoManager* manager;
2807 	view->details = G_TYPE_INSTANCE_GET_PRIVATE (view, NEMO_TYPE_VIEW,
2808 						     NemoViewDetails);
2809 
2810     view->details->load_timer = g_timer_new ();
2811 
2812 	/* Default to true; desktop-icon-view sets to false */
2813 	view->details->show_foreign_files = TRUE;
2814 
2815 	view->details->non_ready_files =
2816 		g_hash_table_new_full (file_and_directory_hash,
2817 				       file_and_directory_equal,
2818 				       (GDestroyNotify)file_and_directory_free,
2819 				       NULL);
2820 
2821 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (view),
2822 					GTK_POLICY_AUTOMATIC,
2823 					GTK_POLICY_AUTOMATIC);
2824 	gtk_scrolled_window_set_hadjustment (GTK_SCROLLED_WINDOW (view), NULL);
2825 	gtk_scrolled_window_set_vadjustment (GTK_SCROLLED_WINDOW (view), NULL);
2826 	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (view), GTK_SHADOW_NONE);
2827 
2828 	gtk_style_context_set_junction_sides (gtk_widget_get_style_context (GTK_WIDGET (view)),
2829 					      GTK_JUNCTION_TOP | GTK_JUNCTION_LEFT);
2830 
2831 	if (set_up_scripts_directory_global ()) {
2832 		scripts_directory = nemo_directory_get_by_uri (scripts_directory_uri);
2833 		add_directory_to_scripts_directory_list (view, scripts_directory);
2834 		nemo_directory_unref (scripts_directory);
2835 	} else {
2836 		g_warning ("Ignoring scripts directory, it may be a broken link\n");
2837 	}
2838 
2839 	if (nemo_should_use_templates_directory ()) {
2840 		templates_uri = nemo_get_templates_directory_uri ();
2841 		templates_directory = nemo_directory_get_by_uri (templates_uri);
2842 		g_free (templates_uri);
2843 		add_directory_to_templates_directory_list (view, templates_directory);
2844 		nemo_directory_unref (templates_directory);
2845 	}
2846 	update_templates_directory (view);
2847 	g_signal_connect_object (nemo_signaller_get_current (),
2848 				 "user_dirs_changed",
2849 				 G_CALLBACK (user_dirs_changed),
2850 				 view, G_CONNECT_SWAPPED);
2851 
2852 	view->details->sort_directories_first =
2853 		g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_SORT_DIRECTORIES_FIRST);
2854 
2855 	g_signal_connect_object (nemo_trash_monitor_get (), "trash_state_changed",
2856 				 G_CALLBACK (nemo_view_trash_state_changed_callback), view, 0);
2857 
2858 	/* React to clipboard changes */
2859 	g_signal_connect_object (nemo_clipboard_monitor_get (), "clipboard_changed",
2860 				 G_CALLBACK (clipboard_changed_callback), view, 0);
2861 
2862 	/* Register to menu provider extension signal managing menu updates */
2863 	g_signal_connect_object (nemo_signaller_get_current (), "popup_menu_changed",
2864 				 G_CALLBACK (nemo_view_update_menus), view, G_CONNECT_SWAPPED);
2865 
2866 	gtk_widget_show (GTK_WIDGET (view));
2867 
2868 	g_signal_connect_swapped (nemo_preferences,
2869 				  "changed::" NEMO_PREFERENCES_ENABLE_DELETE,
2870 				  G_CALLBACK (schedule_update_menus_callback), view);
2871     g_signal_connect_swapped (nemo_menu_config_preferences,
2872                               "changed",
2873                               G_CALLBACK (schedule_update_menus_callback), view);
2874     g_signal_connect_swapped (nemo_preferences,
2875                   "changed::" NEMO_PREFERENCES_SWAP_TRASH_DELETE,
2876                   G_CALLBACK (swap_delete_keybinding_changed_callback), view);
2877 	g_signal_connect_swapped (nemo_preferences,
2878 				  "changed::" NEMO_PREFERENCES_CLICK_POLICY,
2879 				  G_CALLBACK(click_policy_changed_callback),
2880 				  view);
2881     g_signal_connect_swapped (nemo_preferences,
2882                   "changed::" NEMO_PREFERENCES_CLICK_TO_RENAME,
2883                   G_CALLBACK(click_to_rename_changed_callback),
2884                   view);
2885 	g_signal_connect_swapped (nemo_preferences,
2886 				  "changed::" NEMO_PREFERENCES_SORT_DIRECTORIES_FIRST,
2887 				  G_CALLBACK(sort_directories_first_changed_callback), view);
2888 	g_signal_connect_swapped (gnome_lockdown_preferences,
2889 				  "changed::" NEMO_PREFERENCES_LOCKDOWN_COMMAND_LINE,
2890 				  G_CALLBACK (schedule_update_menus), view);
2891 
2892 	g_signal_connect_swapped (nemo_window_state,
2893 				  "changed::" NEMO_WINDOW_STATE_START_WITH_STATUS_BAR,
2894 				  G_CALLBACK (nemo_view_display_selection_info), view);
2895 
2896     g_signal_connect_swapped (nemo_preferences,
2897                   "changed::" NEMO_PREFERENCES_SHOW_BOOKMARKS_IN_TO_MENUS,
2898                   G_CALLBACK (nemo_to_menu_preferences_changed_callback), view);
2899     g_signal_connect_swapped (nemo_preferences,
2900                   "changed::" NEMO_PREFERENCES_SHOW_PLACES_IN_TO_MENUS,
2901                   G_CALLBACK (nemo_to_menu_preferences_changed_callback), view);
2902 
2903     nemo_to_menu_preferences_changed_callback (view);
2904 
2905 	manager = nemo_file_undo_manager_get ();
2906 	g_signal_connect_object (manager, "undo-changed",
2907 				 G_CALLBACK (undo_manager_changed_cb), view, 0);
2908 
2909     g_signal_connect (nemo_plugin_preferences,
2910                       "changed::" NEMO_PLUGIN_PREFERENCES_DISABLED_SCRIPTS,
2911                       G_CALLBACK (plugin_prefs_changed), view);
2912 
2913 	/* Accessibility */
2914 	atk_object = gtk_widget_get_accessible (GTK_WIDGET (view));
2915 	atk_object_set_name (atk_object, _("Content View"));
2916 	atk_object_set_description (atk_object, _("View of the current folder"));
2917 
2918     view->details->action_manager = nemo_action_manager_new ();
2919 
2920     view->details->action_manager_changed_id =
2921         g_signal_connect_swapped (view->details->action_manager, "changed",
2922                       G_CALLBACK (actions_added_or_changed_callback),
2923                                   view);
2924 
2925     view->details->bookmarks = nemo_bookmark_list_get_default ();
2926 
2927     view->details->bookmarks_changed_id =
2928         g_signal_connect_swapped (view->details->bookmarks, "changed",
2929                       G_CALLBACK (schedule_update_menus),
2930                       view);
2931 }
2932 
2933 static void
disconnect_action_activate(NemoAction * action,NemoView * view)2934 disconnect_action_activate (NemoAction *action, NemoView *view)
2935 {
2936     g_signal_handlers_disconnect_by_func (action, run_action_callback, view);
2937 }
2938 
2939 static void
real_unmerge_menus(NemoView * view)2940 real_unmerge_menus (NemoView *view)
2941 {
2942 	GtkUIManager *ui_manager;
2943 
2944 	if (view->details->window == NULL) {
2945 		return;
2946 	}
2947     if (GTK_IS_ACTION_GROUP (view->details->copy_move_action_groups[0])) {
2948         disconnect_bookmark_signals (view);
2949     }
2950 
2951 	ui_manager = nemo_window_get_ui_manager (view->details->window);
2952 
2953 	nemo_ui_unmerge_ui (ui_manager,
2954 				&view->details->dir_merge_id,
2955 				&view->details->dir_action_group);
2956 	nemo_ui_unmerge_ui (ui_manager,
2957 				&view->details->extensions_menu_merge_id,
2958 				&view->details->extensions_menu_action_group);
2959 	nemo_ui_unmerge_ui (ui_manager,
2960 				&view->details->open_with_merge_id,
2961 				&view->details->open_with_action_group);
2962 	nemo_ui_unmerge_ui (ui_manager,
2963 				&view->details->scripts_merge_id,
2964 				&view->details->scripts_action_group);
2965 	nemo_ui_unmerge_ui (ui_manager,
2966 				&view->details->templates_merge_id,
2967 				&view->details->templates_action_group);
2968 
2969     if (view->details->actions_action_group) {
2970         GList *action_list;
2971 
2972         action_list = gtk_action_group_list_actions (view->details->actions_action_group);
2973         g_list_foreach (action_list, (GFunc) disconnect_action_activate, view);
2974 
2975         g_list_free (action_list);
2976     }
2977 
2978     nemo_ui_unmerge_ui (ui_manager,
2979                 &view->details->actions_merge_id,
2980                 &view->details->actions_action_group);
2981     int i;
2982     for (i = 0; i < 4; i++) {
2983         nemo_ui_unmerge_ui (ui_manager,
2984                 &view->details->copy_move_merge_ids[i],
2985                 &view->details->copy_move_action_groups[i]);
2986     }
2987 }
2988 
2989 static void
nemo_view_destroy(GtkWidget * object)2990 nemo_view_destroy (GtkWidget *object)
2991 {
2992 	NemoView *view;
2993 	GList *node, *next;
2994 
2995 	view = NEMO_VIEW (object);
2996 
2997 	disconnect_model_handlers (view);
2998 
2999     if (view->details->bookmarks_changed_id != 0) {
3000         g_signal_handler_disconnect (view->details->bookmarks,
3001                          view->details->bookmarks_changed_id);
3002         view->details->bookmarks_changed_id = 0;
3003     }
3004 
3005     if (view->details->action_manager_changed_id != 0) {
3006         g_signal_handler_disconnect (view->details->action_manager,
3007                          view->details->action_manager_changed_id);
3008         view->details->action_manager_changed_id = 0;
3009     }
3010     g_clear_object (&view->details->action_manager);
3011 
3012 	nemo_view_unmerge_menus (view);
3013 
3014 	/* We don't own the window, so no unref */
3015 	view->details->slot = NULL;
3016 	view->details->window = NULL;
3017 
3018 	nemo_view_stop_loading (view);
3019 
3020 	for (node = view->details->scripts_directory_list; node != NULL; node = next) {
3021 		next = node->next;
3022 		remove_directory_from_scripts_directory_list (view, node->data);
3023 	}
3024 
3025 	for (node = view->details->templates_directory_list; node != NULL; node = next) {
3026 		next = node->next;
3027 		remove_directory_from_templates_directory_list (view, node->data);
3028 	}
3029 
3030 	while (view->details->subdirectory_list != NULL) {
3031 		nemo_view_remove_subdirectory (view,
3032 						   view->details->subdirectory_list->data);
3033 	}
3034 
3035 	remove_update_menus_timeout_callback (view);
3036 	remove_update_status_idle_callback (view);
3037 
3038 	if (view->details->display_selection_idle_id != 0) {
3039 		g_source_remove (view->details->display_selection_idle_id);
3040 		view->details->display_selection_idle_id = 0;
3041 	}
3042 
3043 	if (view->details->reveal_selection_idle_id != 0) {
3044 		g_source_remove (view->details->reveal_selection_idle_id);
3045 		view->details->reveal_selection_idle_id = 0;
3046 	}
3047 
3048 	if (view->details->delayed_rename_file_id != 0) {
3049 		g_source_remove (view->details->delayed_rename_file_id);
3050 		view->details->delayed_rename_file_id = 0;
3051 	}
3052 
3053 	if (view->details->model) {
3054 		nemo_directory_unref (view->details->model);
3055 		view->details->model = NULL;
3056 	}
3057 
3058 	if (view->details->directory_as_file) {
3059 		nemo_file_unref (view->details->directory_as_file);
3060 		view->details->directory_as_file = NULL;
3061 	}
3062 
3063     g_signal_handlers_disconnect_by_func (nemo_plugin_preferences, G_CALLBACK (plugin_prefs_changed), view);
3064 
3065 	GTK_WIDGET_CLASS (nemo_view_parent_class)->destroy (object);
3066 }
3067 
3068 static void
nemo_view_finalize(GObject * object)3069 nemo_view_finalize (GObject *object)
3070 {
3071 	NemoView *view;
3072 
3073 	view = NEMO_VIEW (object);
3074 
3075 	g_signal_handlers_disconnect_by_func (nemo_preferences,
3076 					      schedule_update_menus_callback, view);
3077 	g_signal_handlers_disconnect_by_func (nemo_preferences,
3078 					      click_policy_changed_callback, view);
3079     g_signal_handlers_disconnect_by_func (nemo_preferences,
3080                           click_to_rename_changed_callback, view);
3081 	g_signal_handlers_disconnect_by_func (nemo_preferences,
3082 					      sort_directories_first_changed_callback, view);
3083 	g_signal_handlers_disconnect_by_func (nemo_window_state,
3084 					      nemo_view_display_selection_info, view);
3085     g_signal_handlers_disconnect_by_func (nemo_menu_config_preferences,
3086                           schedule_update_menus_callback, view);
3087 
3088 	g_signal_handlers_disconnect_by_func (gnome_lockdown_preferences,
3089 					      schedule_update_menus, view);
3090 
3091     g_signal_handlers_disconnect_by_func (nemo_preferences,
3092                           nemo_to_menu_preferences_changed_callback, view);
3093 
3094     g_signal_handlers_disconnect_by_func (nemo_preferences,
3095                           schedule_update_menus, view);
3096 
3097 	unschedule_pop_up_location_context_menu (view);
3098 	if (view->details->location_popup_event != NULL) {
3099 		gdk_event_free ((GdkEvent *) view->details->location_popup_event);
3100 	}
3101 
3102     g_clear_pointer (&view->details->load_timer, g_timer_destroy);
3103 
3104 	g_hash_table_destroy (view->details->non_ready_files);
3105 
3106 	G_OBJECT_CLASS (nemo_view_parent_class)->finalize (object);
3107 }
3108 
3109 /**
3110  * nemo_view_display_selection_info:
3111  *
3112  * Display information about the current selection, and notify the view frame of the changed selection.
3113  * @view: NemoView for which to display selection info.
3114  *
3115  **/
3116 void
nemo_view_display_selection_info(NemoView * view)3117 nemo_view_display_selection_info (NemoView *view)
3118 {
3119 	GList *selection;
3120 	goffset non_folder_size;
3121 	gboolean non_folder_size_known;
3122 	guint non_folder_count, folder_count, folder_item_count;
3123 	gboolean folder_item_count_known;
3124 	guint file_item_count;
3125 	GList *p;
3126 	char *first_item_name;
3127 	char *non_folder_str;
3128 	char *folder_count_str;
3129 	char *folder_item_count_str;
3130 	char *status_string;
3131 	char *view_status_string;
3132 	char *free_space_str;
3133 	char *obj_selected_free_space_str;
3134 	NemoFile *file;
3135 
3136 	g_return_if_fail (NEMO_IS_VIEW (view));
3137 
3138 	selection = nemo_view_get_selection (view);
3139 
3140 	folder_item_count_known = TRUE;
3141 	folder_count = 0;
3142 	folder_item_count = 0;
3143 	non_folder_count = 0;
3144 	non_folder_size_known = FALSE;
3145 	non_folder_size = 0;
3146 	first_item_name = NULL;
3147 	folder_count_str = NULL;
3148 	non_folder_str = NULL;
3149 	folder_item_count_str = NULL;
3150 	free_space_str = NULL;
3151 	obj_selected_free_space_str = NULL;
3152 	status_string = NULL;
3153 	view_status_string = NULL;
3154 
3155 	for (p = selection; p != NULL; p = p->next) {
3156 		file = p->data;
3157 		if (nemo_file_is_directory (file)) {
3158 			folder_count++;
3159 			if (nemo_file_get_directory_item_count (file, &file_item_count, NULL)) {
3160 				folder_item_count += file_item_count;
3161 			} else {
3162 				folder_item_count_known = FALSE;
3163 			}
3164 		} else {
3165 			non_folder_count++;
3166 			if (!nemo_file_can_get_size (file)) {
3167 				non_folder_size_known = TRUE;
3168 				non_folder_size += nemo_file_get_size (file);
3169 			}
3170 		}
3171 
3172 		if (first_item_name == NULL) {
3173 			first_item_name = nemo_file_get_display_name (file);
3174 		}
3175 	}
3176 
3177 	nemo_file_list_free (selection);
3178 
3179 	/* Break out cases for localization's sake. But note that there are still pieces
3180 	 * being assembled in a particular order, which may be a problem for some localizers.
3181 	 */
3182 
3183 	if (folder_count != 0) {
3184 		if (folder_count == 1 && non_folder_count == 0) {
3185 			folder_count_str = g_strdup_printf (_("\"%s\" selected"), first_item_name);
3186 		} else {
3187 			folder_count_str = g_strdup_printf (ngettext("%'d folder selected",
3188 								     "%'d folders selected",
3189 								     folder_count),
3190 							    folder_count);
3191 		}
3192 
3193 		if (folder_count == 1) {
3194 			if (!folder_item_count_known) {
3195 				folder_item_count_str = g_strdup ("");
3196 			} else {
3197 				folder_item_count_str = g_strdup_printf (ngettext(" (containing %'d item)",
3198 										  " (containing %'d items)",
3199 										  folder_item_count),
3200 									 folder_item_count);
3201 			}
3202 		}
3203 		else {
3204 			if (!folder_item_count_known) {
3205 				folder_item_count_str = g_strdup ("");
3206 			} else {
3207 				/* translators: this is preceded with a string of form 'N folders' (N more than 1) */
3208 				folder_item_count_str = g_strdup_printf (ngettext(" (containing a total of %'d item)",
3209 										  " (containing a total of %'d items)",
3210 										  folder_item_count),
3211 									 folder_item_count);
3212 			}
3213 
3214 		}
3215 	}
3216 
3217 	if (non_folder_count != 0) {
3218 		char *items_string;
3219 
3220 		if (folder_count == 0) {
3221 			if (non_folder_count == 1) {
3222 				items_string = g_strdup_printf (_("\"%s\" selected"),
3223 								first_item_name);
3224 			} else {
3225 				items_string = g_strdup_printf (ngettext("%'d item selected",
3226 									 "%'d items selected",
3227 									 non_folder_count),
3228 								non_folder_count);
3229 			}
3230 		} else {
3231 			/* Folders selected also, use "other" terminology */
3232 			items_string = g_strdup_printf (ngettext("%'d other item selected",
3233 								 "%'d other items selected",
3234 								 non_folder_count),
3235 							non_folder_count);
3236 		}
3237 
3238 		if (non_folder_size_known) {
3239 			char *size_string;
3240 			int prefix;
3241 
3242 			prefix = nemo_global_preferences_get_size_prefix_preference ();
3243 			size_string = g_format_size_full (non_folder_size, prefix);
3244 			/* This is marked for translation in case a localiser
3245 			 * needs to use something other than parentheses. The
3246 			 * first message gives the number of items selected;
3247 			 * the message in parentheses the size of those items.
3248 			 */
3249 			non_folder_str = g_strdup_printf (_("%s (%s)"),
3250 							  items_string,
3251 							  size_string);
3252 
3253 			g_free (size_string);
3254 			g_free (items_string);
3255 		} else {
3256 			non_folder_str = items_string;
3257 		}
3258 	}
3259 
3260 	free_space_str = nemo_file_get_volume_free_space (view->details->directory_as_file);
3261 	if (free_space_str != NULL) {
3262 		obj_selected_free_space_str = g_strdup_printf (_("Free space: %s"), free_space_str);
3263 	}
3264 	if (folder_count == 0 && non_folder_count == 0)	{
3265 		char *item_count_str;
3266 		guint item_count;
3267 
3268 		item_count = nemo_view_get_item_count (view);
3269 
3270 		item_count_str = g_strdup_printf (ngettext ("%'u item", "%'u items", item_count), item_count);
3271 
3272 		if (free_space_str != NULL) {
3273 			status_string = g_strdup_printf (_("%s, Free space: %s"), item_count_str, free_space_str);
3274 			g_free (item_count_str);
3275 		} else {
3276 			status_string = item_count_str;
3277 		}
3278 
3279 	} else if (folder_count == 0) {
3280 		view_status_string = g_strdup (non_folder_str);
3281 
3282 		if (free_space_str != NULL) {
3283 			/* Marking this for translation, since you
3284 			 * might want to change "," to something else.
3285 			 * After the comma the amount of free space will
3286 			 * be shown.
3287 			 */
3288 			status_string = g_strdup_printf (_("%s, %s"),
3289 							 non_folder_str,
3290 							 obj_selected_free_space_str);
3291 		}
3292 	} else if (non_folder_count == 0) {
3293 		/* No use marking this for translation, since you
3294 		 * can't reorder the strings, which is the main thing
3295 		 * you'd want to do.
3296 		 */
3297 		view_status_string = g_strdup_printf ("%s%s",
3298 						      folder_count_str,
3299 						      folder_item_count_str);
3300 
3301 		if (free_space_str != NULL) {
3302 			/* Marking this for translation, since you
3303 			 * might want to change "," to something else.
3304 			 * After the comma the amount of free space will
3305 			 * be shown.
3306 			 */
3307 			status_string = g_strdup_printf (_("%s%s, %s"),
3308 							 folder_count_str,
3309 							 folder_item_count_str,
3310 							 obj_selected_free_space_str);
3311 		}
3312 	} else {
3313 		/* This is marked for translation in case a localizer
3314 		 * needs to change ", " to something else. The comma
3315 		 * is between the message about the number of folders
3316 		 * and the number of items in those folders and the
3317 		 * message about the number of other items and the
3318 		 * total size of those items.
3319 		 */
3320 		view_status_string = g_strdup_printf (_("%s%s, %s"),
3321 						      folder_count_str,
3322 						      folder_item_count_str,
3323 						      non_folder_str);
3324 
3325 		if (obj_selected_free_space_str != NULL) {
3326 			/* This is marked for translation in case a localizer
3327 			 * needs to change ", " to something else. The first comma
3328 			 * is between the message about the number of folders
3329 			 * and the number of items in those folders and the
3330 			 * message about the number of other items and the
3331 			 * total size of those items. After the second comma
3332 			 * the free space is written.
3333 			 */
3334 			status_string = g_strdup_printf (_("%s%s, %s, %s"),
3335 							 folder_count_str,
3336 							 folder_item_count_str,
3337 							 non_folder_str,
3338 							 obj_selected_free_space_str);
3339 		}
3340 	}
3341 
3342 	g_free (free_space_str);
3343 	g_free (obj_selected_free_space_str);
3344 	g_free (first_item_name);
3345 	g_free (folder_count_str);
3346 	g_free (folder_item_count_str);
3347 	g_free (non_folder_str);
3348 
3349 	if (status_string == NULL) {
3350 		status_string = g_strdup (view_status_string);
3351 	}
3352 
3353 	nemo_window_slot_set_status (view->details->slot,
3354 					 status_string,
3355 					 view_status_string);
3356 
3357 	g_free (status_string);
3358 	g_free (view_status_string);
3359 }
3360 
3361 static void
nemo_view_send_selection_change(NemoView * view)3362 nemo_view_send_selection_change (NemoView *view)
3363 {
3364 	g_signal_emit (view, signals[SELECTION_CHANGED], 0);
3365 
3366 	view->details->send_selection_change_to_shell = FALSE;
3367 }
3368 
3369 void
nemo_view_load_location(NemoView * nemo_view,GFile * location)3370 nemo_view_load_location (NemoView *nemo_view,
3371 			     GFile        *location)
3372 {
3373 	NemoDirectory *directory;
3374 	NemoView *directory_view;
3375 
3376 	directory_view = NEMO_VIEW (nemo_view);
3377 
3378 	directory = nemo_directory_get (location);
3379 	load_directory (directory_view, directory);
3380 	nemo_directory_unref (directory);
3381 }
3382 
3383 static gboolean
reveal_selection_idle_callback(gpointer data)3384 reveal_selection_idle_callback (gpointer data)
3385 {
3386 	NemoView *view;
3387 
3388 	view = NEMO_VIEW (data);
3389 
3390 	view->details->reveal_selection_idle_id = 0;
3391 	nemo_view_reveal_selection (view);
3392 
3393 	return FALSE;
3394 }
3395 
3396 static gboolean
idle_timer_report(gpointer user_data)3397 idle_timer_report (gpointer user_data)
3398 {
3399     g_return_val_if_fail (NEMO_IS_VIEW (user_data), G_SOURCE_REMOVE);
3400 
3401     NemoView *view = NEMO_VIEW (user_data);
3402 
3403     g_printerr ("Idle...Folder load time: %f seconds\n", g_timer_elapsed (view->details->load_timer, NULL));
3404 
3405     return G_SOURCE_REMOVE;
3406 }
3407 
3408 static void
done_loading(NemoView * view,gboolean all_files_seen)3409 done_loading (NemoView *view,
3410 	      gboolean all_files_seen)
3411 {
3412 	GList *selection;
3413 
3414 	if (!view->details->loading) {
3415 		return;
3416 	}
3417 
3418 	/* This can be called during destruction, in which case there
3419 	 * is no NemoWindow any more.
3420 	 */
3421 	if (view->details->window != NULL) {
3422 		if (all_files_seen) {
3423 			nemo_window_report_load_complete (view->details->window, NEMO_VIEW (view));
3424 		}
3425 
3426 		schedule_update_menus (view);
3427 		schedule_update_status (view);
3428 		reset_update_interval (view);
3429 
3430 		selection = view->details->pending_selection;
3431 		if (selection != NULL && all_files_seen) {
3432 			view->details->pending_selection = NULL;
3433 
3434 			view->details->selection_change_is_due_to_shell = TRUE;
3435 			nemo_view_call_set_selection (view, selection);
3436 			view->details->selection_change_is_due_to_shell = FALSE;
3437 
3438 			if (NEMO_IS_LIST_VIEW (view)) {
3439 				/* HACK: We should be able to directly call reveal_selection here,
3440 				 * but at this point the GtkTreeView hasn't allocated the new nodes
3441 				 * yet, and it has a bug in the scroll calculation dealing with this
3442 				 * special case. It would always make the selection the top row, even
3443 				 * if no scrolling would be neccessary to reveal it. So we let it
3444 				 * allocate before revealing.
3445 				 */
3446 				if (view->details->reveal_selection_idle_id != 0) {
3447 					g_source_remove (view->details->reveal_selection_idle_id);
3448 				}
3449 				view->details->reveal_selection_idle_id =
3450 					g_idle_add (reveal_selection_idle_callback, view);
3451 			} else {
3452 				nemo_view_reveal_selection (view);
3453 			}
3454 		}
3455 		g_list_free_full (selection, g_object_unref);
3456 		nemo_view_display_selection_info (view);
3457 	}
3458 
3459 	view->details->loading = FALSE;
3460 	g_signal_emit (view, signals[END_LOADING], 0, all_files_seen);
3461 
3462     if (g_getenv("NEMO_BENCHMARK_LOADING")) {
3463         if (nemo_startup_timer != NULL) {
3464             g_printerr ("Nemo startup time: %f seconds\n", g_timer_elapsed (nemo_startup_timer, NULL));
3465             g_clear_pointer (&nemo_startup_timer, g_timer_destroy);
3466         }
3467 
3468         g_printerr ("Folder load time: %f seconds\n", g_timer_elapsed (view->details->load_timer, NULL));
3469 
3470         g_idle_add_full (1000, (GSourceFunc) idle_timer_report, view, NULL);
3471     }
3472 }
3473 
3474 typedef struct {
3475 	GHashTable *debuting_files;
3476 	GList	   *added_files;
3477 } DebutingFilesData;
3478 
3479 static void
debuting_files_data_free(DebutingFilesData * data)3480 debuting_files_data_free (DebutingFilesData *data)
3481 {
3482 	g_hash_table_unref (data->debuting_files);
3483 	nemo_file_list_free (data->added_files);
3484 	g_free (data);
3485 }
3486 
3487 /* This signal handler watch for the arrival of the icons created
3488  * as the result of a file operation. Once the last one is detected
3489  * it selects and reveals them all.
3490  */
3491 static void
debuting_files_add_file_callback(NemoView * view,NemoFile * new_file,NemoDirectory * directory,DebutingFilesData * data)3492 debuting_files_add_file_callback (NemoView *view,
3493 				  NemoFile *new_file,
3494 				  NemoDirectory *directory,
3495 				  DebutingFilesData *data)
3496 {
3497 	GFile *location;
3498 
3499 	location = nemo_file_get_location (new_file);
3500 
3501 	if (g_hash_table_remove (data->debuting_files, location)) {
3502 		nemo_file_ref (new_file);
3503 		data->added_files = g_list_prepend (data->added_files, new_file);
3504 
3505 		if (g_hash_table_size (data->debuting_files) == 0) {
3506 			nemo_view_call_set_selection (view, data->added_files);
3507 			nemo_view_reveal_selection (view);
3508 			g_signal_handlers_disconnect_by_func (view,
3509 							      G_CALLBACK (debuting_files_add_file_callback),
3510 							      data);
3511 		}
3512 	}
3513 
3514 	g_object_unref (location);
3515 }
3516 
3517 typedef struct {
3518 	GList		*added_files;
3519 	NemoView *directory_view;
3520 } CopyMoveDoneData;
3521 
3522 static void
copy_move_done_data_free(CopyMoveDoneData * data)3523 copy_move_done_data_free (CopyMoveDoneData *data)
3524 {
3525 	g_assert (data != NULL);
3526 
3527 	if (data->directory_view != NULL) {
3528 		g_object_remove_weak_pointer (G_OBJECT (data->directory_view),
3529 					      (gpointer *) &data->directory_view);
3530 	}
3531 
3532 	nemo_file_list_free (data->added_files);
3533 	g_free (data);
3534 }
3535 
3536 static void
pre_copy_move_add_file_callback(NemoView * view,NemoFile * new_file,NemoDirectory * directory,CopyMoveDoneData * data)3537 pre_copy_move_add_file_callback (NemoView *view,
3538 				 NemoFile *new_file,
3539 				 NemoDirectory *directory,
3540 				 CopyMoveDoneData *data)
3541 {
3542 	nemo_file_ref (new_file);
3543 	data->added_files = g_list_prepend (data->added_files, new_file);
3544 }
3545 
3546 /* This needs to be called prior to nemo_file_operations_copy_move.
3547  * It hooks up a signal handler to catch any icons that get added before
3548  * the copy_done_callback is invoked. The return value should  be passed
3549  * as the data for uri_copy_move_done_callback.
3550  */
3551 static CopyMoveDoneData *
pre_copy_move(NemoView * directory_view)3552 pre_copy_move (NemoView *directory_view)
3553 {
3554 	CopyMoveDoneData *copy_move_done_data;
3555 
3556 	copy_move_done_data = g_new0 (CopyMoveDoneData, 1);
3557 	copy_move_done_data->directory_view = directory_view;
3558 
3559 	g_object_add_weak_pointer (G_OBJECT (copy_move_done_data->directory_view),
3560 				   (gpointer *) &copy_move_done_data->directory_view);
3561 
3562 	/* We need to run after the default handler adds the folder we want to
3563 	 * operate on. The ADD_FILE signal is registered as G_SIGNAL_RUN_LAST, so we
3564 	 * must use connect_after.
3565 	 */
3566 	g_signal_connect (directory_view, "add_file",
3567 			  G_CALLBACK (pre_copy_move_add_file_callback), copy_move_done_data);
3568 
3569 	return copy_move_done_data;
3570 }
3571 
3572 /* This function is used to pull out any debuting uris that were added
3573  * and (as a side effect) remove them from the debuting uri hash table.
3574  */
3575 static gboolean
copy_move_done_partition_func(gpointer data,gpointer callback_data)3576 copy_move_done_partition_func (gpointer data, gpointer callback_data)
3577 {
3578  	GFile *location;
3579  	gboolean result;
3580 
3581 	location = nemo_file_get_location (NEMO_FILE (data));
3582 	result = g_hash_table_remove ((GHashTable *) callback_data, location);
3583 	g_object_unref (location);
3584 
3585 	return result;
3586 }
3587 
3588 static gboolean
remove_not_really_moved_files(gpointer key,gpointer value,gpointer callback_data)3589 remove_not_really_moved_files (gpointer key,
3590 			       gpointer value,
3591 			       gpointer callback_data)
3592 {
3593 	GList **added_files;
3594 	GFile *loc;
3595 
3596 	loc = key;
3597 
3598 	if (GPOINTER_TO_INT (value)) {
3599 		return FALSE;
3600 	}
3601 
3602 	added_files = callback_data;
3603 	*added_files = g_list_prepend (*added_files,
3604 				       nemo_file_get (loc));
3605 	return TRUE;
3606 }
3607 
3608 
3609 /* When this function is invoked, the file operation is over, but all
3610  * the icons may not have been added to the directory view yet, so
3611  * we can't select them yet.
3612  *
3613  * We're passed a hash table of the uri's to look out for, we hook
3614  * up a signal handler to await their arrival.
3615  */
3616 static void
copy_move_done_callback(GHashTable * debuting_files,gboolean success,gpointer data)3617 copy_move_done_callback (GHashTable *debuting_files,
3618 			 gboolean success,
3619 			 gpointer data)
3620 {
3621 	NemoView  *directory_view;
3622 	CopyMoveDoneData *copy_move_done_data;
3623 	DebutingFilesData  *debuting_files_data;
3624 
3625 	copy_move_done_data = (CopyMoveDoneData *) data;
3626 	directory_view = copy_move_done_data->directory_view;
3627 
3628 	if (directory_view != NULL) {
3629 		g_assert (NEMO_IS_VIEW (directory_view));
3630 
3631 		debuting_files_data = g_new (DebutingFilesData, 1);
3632 		debuting_files_data->debuting_files = g_hash_table_ref (debuting_files);
3633 		debuting_files_data->added_files = eel_g_list_partition
3634 			(copy_move_done_data->added_files,
3635 			 copy_move_done_partition_func,
3636 			 debuting_files,
3637 			 &copy_move_done_data->added_files);
3638 
3639 		/* We're passed the same data used by pre_copy_move_add_file_callback, so disconnecting
3640 		 * it will free data. We've already siphoned off the added_files we need, and stashed the
3641 		 * directory_view pointer.
3642 		 */
3643 		g_signal_handlers_disconnect_by_func (directory_view,
3644 						      G_CALLBACK (pre_copy_move_add_file_callback),
3645 						      data);
3646 
3647 		/* Any items in the debuting_files hash table that have
3648 		 * "FALSE" as their value aren't really being copied
3649 		 * or moved, so we can't wait for an add_file signal
3650 		 * to come in for those.
3651 		 */
3652 		g_hash_table_foreach_remove (debuting_files,
3653 					     remove_not_really_moved_files,
3654 					     &debuting_files_data->added_files);
3655 
3656 		if (g_hash_table_size (debuting_files) == 0) {
3657 			/* on the off-chance that all the icons have already been added */
3658 			if (debuting_files_data->added_files != NULL) {
3659 				nemo_view_call_set_selection (directory_view,
3660 								  debuting_files_data->added_files);
3661 				nemo_view_reveal_selection (directory_view);
3662 			}
3663 			debuting_files_data_free (debuting_files_data);
3664 		} else {
3665 			/* We need to run after the default handler adds the folder we want to
3666 			 * operate on. The ADD_FILE signal is registered as G_SIGNAL_RUN_LAST, so we
3667 			 * must use connect_after.
3668 			 */
3669 			g_signal_connect_data (directory_view,
3670 					       "add_file",
3671 					       G_CALLBACK (debuting_files_add_file_callback),
3672 					       debuting_files_data,
3673 					       (GClosureNotify) debuting_files_data_free,
3674 					       G_CONNECT_AFTER);
3675 		}
3676 		/* Schedule menu update for undo items */
3677 		schedule_update_menus (directory_view);
3678 	}
3679 
3680 	copy_move_done_data_free (copy_move_done_data);
3681 }
3682 
3683 static gboolean
view_file_still_belongs(NemoView * view,NemoFile * file,NemoDirectory * directory)3684 view_file_still_belongs (NemoView *view,
3685 			 NemoFile *file,
3686 			 NemoDirectory *directory)
3687 {
3688 	if (view->details->model != directory &&
3689 	    g_list_find (view->details->subdirectory_list, directory) == NULL) {
3690 		return FALSE;
3691 	}
3692 
3693 	return nemo_directory_contains_file (directory, file);
3694 }
3695 
3696 static gboolean
still_should_show_file(NemoView * view,NemoFile * file,NemoDirectory * directory)3697 still_should_show_file (NemoView *view, NemoFile *file, NemoDirectory *directory)
3698 {
3699 	return nemo_view_should_show_file (view, file) &&
3700 		view_file_still_belongs (view, file, directory);
3701 }
3702 
3703 static gboolean
ready_to_load(NemoFile * file)3704 ready_to_load (NemoFile *file)
3705 {
3706 	return nemo_file_check_if_ready (file,
3707 					     NEMO_FILE_ATTRIBUTES_FOR_ICON);
3708 }
3709 
3710 static int
compare_files_cover(gconstpointer a,gconstpointer b,gpointer callback_data)3711 compare_files_cover (gconstpointer a, gconstpointer b, gpointer callback_data)
3712 {
3713 	const FileAndDirectory *fad1, *fad2;
3714 	NemoView *view;
3715 
3716 	view = callback_data;
3717 	fad1 = a; fad2 = b;
3718 
3719 	if (fad1->directory < fad2->directory) {
3720 		return -1;
3721 	} else if (fad1->directory > fad2->directory) {
3722 		return 1;
3723 	} else {
3724 		return NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->compare_files (view, fad1->file, fad2->file);
3725 	}
3726 }
3727 static void
sort_files(NemoView * view,GList ** list)3728 sort_files (NemoView *view, GList **list)
3729 {
3730 	*list = g_list_sort_with_data (*list, compare_files_cover, view);
3731 
3732 }
3733 
3734 /* Go through all the new added and changed files.
3735  * Put any that are not ready to load in the non_ready_files hash table.
3736  * Add all the rest to the old_added_files and old_changed_files lists.
3737  * Sort the old_*_files lists if anything was added to them.
3738  */
3739 static void
process_new_files(NemoView * view)3740 process_new_files (NemoView *view)
3741 {
3742 	GList *new_added_files, *new_changed_files, *old_added_files, *old_changed_files;
3743 	GHashTable *non_ready_files;
3744 	GList *node, *next;
3745 	FileAndDirectory *pending;
3746 	gboolean in_non_ready;
3747 
3748 	new_added_files = view->details->new_added_files;
3749 	view->details->new_added_files = NULL;
3750 	new_changed_files = view->details->new_changed_files;
3751 	view->details->new_changed_files = NULL;
3752 
3753 	non_ready_files = view->details->non_ready_files;
3754 
3755 	old_added_files = view->details->old_added_files;
3756 	old_changed_files = view->details->old_changed_files;
3757 
3758 	/* Newly added files go into the old_added_files list if they're
3759 	 * ready, and into the hash table if they're not.
3760 	 */
3761 	for (node = new_added_files; node != NULL; node = next) {
3762 		next = node->next;
3763 		pending = (FileAndDirectory *)node->data;
3764 		in_non_ready = g_hash_table_lookup (non_ready_files, pending) != NULL;
3765 		if (nemo_view_should_show_file (view, pending->file)) {
3766 			if (ready_to_load (pending->file)) {
3767 				if (in_non_ready) {
3768 					g_hash_table_remove (non_ready_files, pending);
3769 				}
3770 				new_added_files = g_list_delete_link (new_added_files, node);
3771 				old_added_files = g_list_prepend (old_added_files, pending);
3772 			} else {
3773 				if (!in_non_ready) {
3774 					new_added_files = g_list_delete_link (new_added_files, node);
3775 					g_hash_table_insert (non_ready_files, pending, pending);
3776 				}
3777 			}
3778 		}
3779 	}
3780 	file_and_directory_list_free (new_added_files);
3781 
3782 	/* Newly changed files go into the old_added_files list if they're ready
3783 	 * and were seen non-ready in the past, into the old_changed_files list
3784 	 * if they are read and were not seen non-ready in the past, and into
3785 	 * the hash table if they're not ready.
3786 	 */
3787 	for (node = new_changed_files; node != NULL; node = next) {
3788 		next = node->next;
3789 		pending = (FileAndDirectory *)node->data;
3790 		if (!still_should_show_file (view, pending->file, pending->directory) || ready_to_load (pending->file)) {
3791 			if (g_hash_table_lookup (non_ready_files, pending) != NULL) {
3792 				g_hash_table_remove (non_ready_files, pending);
3793 				if (still_should_show_file (view, pending->file, pending->directory)) {
3794 					new_changed_files = g_list_delete_link (new_changed_files, node);
3795 					old_added_files = g_list_prepend (old_added_files, pending);
3796 				}
3797 			} else if (nemo_view_should_show_file (view, pending->file)) {
3798 				new_changed_files = g_list_delete_link (new_changed_files, node);
3799 				old_changed_files = g_list_prepend (old_changed_files, pending);
3800 			}
3801 		}
3802 	}
3803 	file_and_directory_list_free (new_changed_files);
3804 
3805 	/* If any files were added to old_added_files, then resort it. */
3806 	if (old_added_files != view->details->old_added_files) {
3807 		view->details->old_added_files = old_added_files;
3808 		sort_files (view, &view->details->old_added_files);
3809 	}
3810 
3811 	/* Resort old_changed_files too, since file attributes
3812 	 * relevant to sorting could have changed.
3813 	 */
3814 	if (old_changed_files != view->details->old_changed_files) {
3815 		view->details->old_changed_files = old_changed_files;
3816 		sort_files (view, &view->details->old_changed_files);
3817 	}
3818 
3819 }
3820 
3821 static void
process_old_files(NemoView * view)3822 process_old_files (NemoView *view)
3823 {
3824 	GList *files_added, *files_changed, *node;
3825 	FileAndDirectory *pending;
3826 	GList *selection, *files;
3827 	gboolean send_selection_change;
3828 
3829 	files_added = view->details->old_added_files;
3830 	files_changed = view->details->old_changed_files;
3831 
3832 	send_selection_change = FALSE;
3833 
3834 	if (files_added != NULL || files_changed != NULL) {
3835 		g_signal_emit (view, signals[BEGIN_FILE_CHANGES], 0);
3836 
3837 		for (node = files_added; node != NULL; node = node->next) {
3838 			pending = node->data;
3839 			g_signal_emit (view,
3840 				       signals[ADD_FILE], 0, pending->file, pending->directory);
3841 		}
3842 
3843 		for (node = files_changed; node != NULL; node = node->next) {
3844 			pending = node->data;
3845 			g_signal_emit (view,
3846 				       signals[still_should_show_file (view, pending->file, pending->directory)
3847 					       ? FILE_CHANGED : REMOVE_FILE], 0,
3848 				       pending->file, pending->directory);
3849 		}
3850 
3851 		g_signal_emit (view, signals[END_FILE_CHANGES], 0);
3852 
3853 		if (files_changed != NULL) {
3854 			selection = nemo_view_get_selection (view);
3855 			files = file_and_directory_list_to_files (files_changed);
3856 			send_selection_change = eel_g_lists_sort_and_check_for_intersection
3857 				(&files, &selection);
3858 			nemo_file_list_free (files);
3859 			nemo_file_list_free (selection);
3860 		}
3861 
3862 		file_and_directory_list_free (view->details->old_added_files);
3863 		view->details->old_added_files = NULL;
3864 
3865 		file_and_directory_list_free (view->details->old_changed_files);
3866 		view->details->old_changed_files = NULL;
3867 	}
3868 
3869 	if (send_selection_change) {
3870 		/* Send a selection change since some file names could
3871 		 * have changed.
3872 		 */
3873 		nemo_view_send_selection_change (view);
3874 	}
3875 }
3876 
3877 static void
display_pending_files(NemoView * view)3878 display_pending_files (NemoView *view)
3879 {
3880 
3881 	/* Don't dispatch any updates while the view is frozen. */
3882 	if (view->details->updates_frozen) {
3883 		return;
3884 	}
3885 
3886 	process_new_files (view);
3887 	process_old_files (view);
3888 
3889 	if (view->details->model != NULL
3890 	    && nemo_directory_are_all_files_seen (view->details->model)
3891 	    && g_hash_table_size (view->details->non_ready_files) == 0) {
3892 		done_loading (view, TRUE);
3893 	}
3894 }
3895 
3896 void
nemo_view_freeze_updates(NemoView * view)3897 nemo_view_freeze_updates (NemoView *view)
3898 {
3899 	view->details->updates_frozen = TRUE;
3900 	view->details->updates_queued = 0;
3901 	view->details->needs_reload = FALSE;
3902 }
3903 
3904 void
nemo_view_unfreeze_updates(NemoView * view)3905 nemo_view_unfreeze_updates (NemoView *view)
3906 {
3907 	view->details->updates_frozen = FALSE;
3908 
3909 	if (view->details->needs_reload) {
3910 		view->details->needs_reload = FALSE;
3911 		if (view->details->model != NULL) {
3912 			load_directory (view, view->details->model);
3913 		}
3914 	} else {
3915 		schedule_idle_display_of_pending_files (view);
3916 	}
3917 }
3918 
3919 static gboolean
display_selection_info_idle_callback(gpointer data)3920 display_selection_info_idle_callback (gpointer data)
3921 {
3922 	NemoView *view;
3923 
3924 	view = NEMO_VIEW (data);
3925 
3926 	g_object_ref (G_OBJECT (view));
3927 
3928 	view->details->display_selection_idle_id = 0;
3929 	nemo_view_display_selection_info (view);
3930 	if (view->details->send_selection_change_to_shell) {
3931 		nemo_view_send_selection_change (view);
3932 	}
3933 
3934 	g_object_unref (G_OBJECT (view));
3935 
3936 	return FALSE;
3937 }
3938 
3939 static void
remove_update_menus_timeout_callback(NemoView * view)3940 remove_update_menus_timeout_callback (NemoView *view)
3941 {
3942 	if (view->details->update_menus_timeout_id != 0) {
3943 		g_source_remove (view->details->update_menus_timeout_id);
3944 		view->details->update_menus_timeout_id = 0;
3945 	}
3946 }
3947 
3948 static void
update_menus_if_pending(NemoView * view)3949 update_menus_if_pending (NemoView *view)
3950 {
3951 	if (!view->details->menu_states_untrustworthy) {
3952 		return;
3953 	}
3954 
3955 	remove_update_menus_timeout_callback (view);
3956 	nemo_view_update_menus (view);
3957 }
3958 
3959 static gboolean
update_menus_timeout_callback(gpointer data)3960 update_menus_timeout_callback (gpointer data)
3961 {
3962 	NemoView *view;
3963 	view = NEMO_VIEW (data);
3964 
3965 	g_object_ref (G_OBJECT (view));
3966 
3967 	view->details->update_menus_timeout_id = 0;
3968 	nemo_view_update_menus (view);
3969 
3970 	g_object_unref (G_OBJECT (view));
3971 
3972 	return FALSE;
3973 }
3974 
3975 static gboolean
display_pending_callback(gpointer data)3976 display_pending_callback (gpointer data)
3977 {
3978 	NemoView *view;
3979 
3980 	view = NEMO_VIEW (data);
3981 
3982 	g_object_ref (G_OBJECT (view));
3983 
3984 	view->details->display_pending_source_id = 0;
3985 
3986 	display_pending_files (view);
3987 
3988 	g_object_unref (G_OBJECT (view));
3989 
3990 	return FALSE;
3991 }
3992 
3993 static void
schedule_idle_display_of_pending_files(NemoView * view)3994 schedule_idle_display_of_pending_files (NemoView *view)
3995 {
3996 	/* Get rid of a pending source as it might be a timeout */
3997 	unschedule_display_of_pending_files (view);
3998 
3999 	/* We want higher priority than the idle that handles the relayout
4000 	   to avoid a resort on each add. But we still want to allow repaints
4001 	   and other hight prio events while we have pending files to show. */
4002 	view->details->display_pending_source_id =
4003 		g_idle_add_full (G_PRIORITY_DEFAULT_IDLE - 20,
4004 				 display_pending_callback, view, NULL);
4005 }
4006 
4007 static void
schedule_timeout_display_of_pending_files(NemoView * view,guint interval)4008 schedule_timeout_display_of_pending_files (NemoView *view, guint interval)
4009 {
4010  	/* No need to schedule an update if there's already one pending. */
4011 	if (view->details->display_pending_source_id != 0) {
4012  		return;
4013 	}
4014 
4015 	view->details->display_pending_source_id =
4016 		g_timeout_add (interval, display_pending_callback, view);
4017 }
4018 
4019 static void
unschedule_display_of_pending_files(NemoView * view)4020 unschedule_display_of_pending_files (NemoView *view)
4021 {
4022 	/* Get rid of source if it's active. */
4023 	if (view->details->display_pending_source_id != 0) {
4024 		g_source_remove (view->details->display_pending_source_id);
4025 		view->details->display_pending_source_id = 0;
4026 	}
4027 }
4028 
4029 static void
queue_pending_files(NemoView * view,NemoDirectory * directory,GList * files,GList ** pending_list)4030 queue_pending_files (NemoView *view,
4031 		     NemoDirectory *directory,
4032 		     GList *files,
4033 		     GList **pending_list)
4034 {
4035 	if (files == NULL) {
4036 		return;
4037 	}
4038 
4039 	/* Don't queue any more updates if we need to reload anyway */
4040 	if (view->details->needs_reload) {
4041 		return;
4042 	}
4043 
4044 	if (view->details->updates_frozen) {
4045 		view->details->updates_queued += g_list_length (files);
4046 		/* Mark the directory for reload when there are too much queued
4047 		 * changes to prevent the pending list from growing infinitely.
4048 		 */
4049 		if (view->details->updates_queued > MAX_QUEUED_UPDATES) {
4050 			view->details->needs_reload = TRUE;
4051 			return;
4052 		}
4053 	}
4054 
4055 	*pending_list = g_list_concat (file_and_directory_list_from_files (directory, files),
4056 				       *pending_list);
4057 
4058     schedule_timeout_display_of_pending_files (view, view->details->update_interval);
4059 }
4060 
4061 static void
remove_changes_timeout_callback(NemoView * view)4062 remove_changes_timeout_callback (NemoView *view)
4063 {
4064 	if (view->details->changes_timeout_id != 0) {
4065 		g_source_remove (view->details->changes_timeout_id);
4066 		view->details->changes_timeout_id = 0;
4067 	}
4068 }
4069 
4070 static void
reset_update_interval(NemoView * view)4071 reset_update_interval (NemoView *view)
4072 {
4073 	view->details->update_interval = UPDATE_INTERVAL_MIN;
4074 	remove_changes_timeout_callback (view);
4075 	/* Reschedule a pending timeout to idle */
4076 	if (view->details->display_pending_source_id != 0) {
4077 		schedule_idle_display_of_pending_files (view);
4078 	}
4079 }
4080 
4081 static gboolean
changes_timeout_callback(gpointer data)4082 changes_timeout_callback (gpointer data)
4083 {
4084 	gint64 now;
4085 	gint64 time_delta;
4086 	gboolean ret;
4087 	NemoView *view;
4088 	view = NEMO_VIEW (data);
4089 
4090 	g_object_ref (G_OBJECT (view));
4091 
4092 	now = g_get_monotonic_time ();
4093 	time_delta = now - view->details->last_queued;
4094 
4095 	if (time_delta < UPDATE_INTERVAL_RESET*1000) {
4096 		if (view->details->update_interval < UPDATE_INTERVAL_MAX &&
4097 		    view->details->loading) {
4098 			/* Increase */
4099 			view->details->update_interval += UPDATE_INTERVAL_INC;
4100 		}
4101 		ret = TRUE;
4102 	} else {
4103 		/* Reset */
4104 		reset_update_interval (view);
4105 		ret = FALSE;
4106 	}
4107 
4108 	g_object_unref (G_OBJECT (view));
4109 
4110 	return ret;
4111 }
4112 
4113 static void
schedule_changes(NemoView * view)4114 schedule_changes (NemoView *view)
4115 {
4116 	/* Remember when the change was queued */
4117 	view->details->last_queued = g_get_monotonic_time ();
4118 
4119 	/* No need to schedule if there are already changes pending or during loading */
4120 	if (view->details->changes_timeout_id != 0 ||
4121 	    view->details->loading) {
4122 		return;
4123 	}
4124 
4125 	view->details->changes_timeout_id =
4126 		g_timeout_add (UPDATE_INTERVAL_TIMEOUT_INTERVAL, changes_timeout_callback, view);
4127 }
4128 
4129 static void
files_added_callback(NemoDirectory * directory,GList * files,gpointer callback_data)4130 files_added_callback (NemoDirectory *directory,
4131 		      GList *files,
4132 		      gpointer callback_data)
4133 {
4134 	NemoView *view;
4135 	GtkWindow *window;
4136 	char *uri;
4137 
4138 	view = NEMO_VIEW (callback_data);
4139 
4140 	window = nemo_view_get_containing_window (view);
4141 	uri = nemo_view_get_uri (view);
4142 	DEBUG_FILES (files, "Files added in window %p: %s",
4143 		     window, uri ? uri : "(no directory)");
4144 	g_free (uri);
4145 
4146 	schedule_changes (view);
4147 
4148 	queue_pending_files (view, directory, files, &view->details->new_added_files);
4149 
4150 	/* The number of items could have changed */
4151 	schedule_update_status (view);
4152 }
4153 
4154 static void
files_changed_callback(NemoDirectory * directory,GList * files,gpointer callback_data)4155 files_changed_callback (NemoDirectory *directory,
4156 			GList *files,
4157 			gpointer callback_data)
4158 {
4159 	NemoView *view;
4160 	GtkWindow *window;
4161 	char *uri;
4162 
4163 	view = NEMO_VIEW (callback_data);
4164 
4165 	window = nemo_view_get_containing_window (view);
4166 	uri = nemo_view_get_uri (view);
4167 	DEBUG_FILES (files, "Files changed in window %p: %s",
4168 		     window, uri ? uri : "(no directory)");
4169 	g_free (uri);
4170 
4171 	schedule_changes (view);
4172 
4173 	queue_pending_files (view, directory, files, &view->details->new_changed_files);
4174 
4175 	/* The free space or the number of items could have changed */
4176 	schedule_update_status (view);
4177 
4178 	/* A change in MIME type could affect the Open with menu, for
4179 	 * one thing, so we need to update menus when files change.
4180 	 */
4181 	schedule_update_menus (view);
4182 }
4183 
4184 static void
done_loading_callback(NemoDirectory * directory,gpointer callback_data)4185 done_loading_callback (NemoDirectory *directory,
4186 		       gpointer callback_data)
4187 {
4188 	NemoView *view;
4189 
4190 	view = NEMO_VIEW (callback_data);
4191 
4192 	process_new_files (view);
4193 	if (g_hash_table_size (view->details->non_ready_files) == 0) {
4194 		/* Unschedule a pending update and schedule a new one with the minimal
4195 		 * update interval. This gives the view a short chance at gathering the
4196 		 * (cached) deep counts.
4197 		 */
4198 		unschedule_display_of_pending_files (view);
4199 		schedule_timeout_display_of_pending_files (view, UPDATE_INTERVAL_MIN);
4200 	}
4201 }
4202 
4203 static void
load_error_callback(NemoDirectory * directory,GError * error,gpointer callback_data)4204 load_error_callback (NemoDirectory *directory,
4205 		     GError *error,
4206 		     gpointer callback_data)
4207 {
4208 	NemoView *view;
4209 
4210 	view = NEMO_VIEW (callback_data);
4211 
4212 	/* FIXME: By doing a stop, we discard some pending files. Is
4213 	 * that OK?
4214 	 */
4215 	nemo_view_stop_loading (view);
4216 
4217     nemo_window_back_or_forward (NEMO_WINDOW (view->details->window),
4218                                  TRUE, 0, FALSE);
4219 
4220 	/* Emit a signal to tell subclasses that a load error has
4221 	 * occurred, so they can handle it in the UI.
4222 	 */
4223 	g_signal_emit (view,
4224 		       signals[LOAD_ERROR], 0, error);
4225 }
4226 
4227 static void
real_load_error(NemoView * view,GError * error)4228 real_load_error (NemoView *view, GError *error)
4229 {
4230 	/* Report only one error per failed directory load (from the UI
4231 	 * point of view, not from the NemoDirectory point of view).
4232 	 * Otherwise you can get multiple identical errors caused by
4233 	 * unrelated code that just happens to try to iterate this
4234 	 * directory.
4235 	 */
4236 	if (!view->details->reported_load_error) {
4237 		nemo_report_error_loading_directory
4238 			(nemo_view_get_directory_as_file (view),
4239 			 error,
4240 			 nemo_view_get_containing_window (view));
4241 	}
4242 	view->details->reported_load_error = TRUE;
4243 }
4244 
4245 void
nemo_view_add_subdirectory(NemoView * view,NemoDirectory * directory)4246 nemo_view_add_subdirectory (NemoView  *view,
4247 				NemoDirectory*directory)
4248 {
4249 	NemoFileAttributes attributes;
4250 
4251 	g_assert (!g_list_find (view->details->subdirectory_list, directory));
4252 
4253 	nemo_directory_ref (directory);
4254 
4255 	attributes =
4256 		NEMO_FILE_ATTRIBUTES_FOR_ICON |
4257 		NEMO_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT |
4258 		NEMO_FILE_ATTRIBUTE_INFO |
4259 		NEMO_FILE_ATTRIBUTE_LINK_INFO |
4260 		NEMO_FILE_ATTRIBUTE_MOUNT |
4261 		NEMO_FILE_ATTRIBUTE_EXTENSION_INFO;
4262 
4263 	nemo_directory_file_monitor_add (directory,
4264 					     &view->details->model,
4265 					     view->details->show_hidden_files,
4266 					     attributes,
4267 					     files_added_callback, view);
4268 
4269 	g_signal_connect
4270 		(directory, "files_added",
4271 		 G_CALLBACK (files_added_callback), view);
4272 	g_signal_connect
4273 		(directory, "files_changed",
4274 		 G_CALLBACK (files_changed_callback), view);
4275 
4276 	view->details->subdirectory_list = g_list_prepend (
4277 							   view->details->subdirectory_list, directory);
4278 }
4279 
4280 void
nemo_view_remove_subdirectory(NemoView * view,NemoDirectory * directory)4281 nemo_view_remove_subdirectory (NemoView  *view,
4282 				   NemoDirectory*directory)
4283 {
4284 	g_assert (g_list_find (view->details->subdirectory_list, directory));
4285 
4286 	view->details->subdirectory_list = g_list_remove (
4287 							  view->details->subdirectory_list, directory);
4288 
4289 	g_signal_handlers_disconnect_by_func (directory,
4290 					      G_CALLBACK (files_added_callback),
4291 					      view);
4292 	g_signal_handlers_disconnect_by_func (directory,
4293 					      G_CALLBACK (files_changed_callback),
4294 					      view);
4295 
4296 	nemo_directory_file_monitor_remove (directory, &view->details->model);
4297 
4298 	nemo_directory_unref (directory);
4299 }
4300 
4301 /**
4302  * nemo_view_get_loading:
4303  * @view: an #NemoView.
4304  *
4305  * Return value: #gboolean inicating whether @view is currently loaded.
4306  *
4307  **/
4308 gboolean
nemo_view_get_loading(NemoView * view)4309 nemo_view_get_loading (NemoView *view)
4310 {
4311 	g_return_val_if_fail (NEMO_IS_VIEW (view), FALSE);
4312 
4313 	return view->details->loading;
4314 }
4315 
4316 GtkUIManager *
nemo_view_get_ui_manager(NemoView * view)4317 nemo_view_get_ui_manager (NemoView  *view)
4318 {
4319 	if (view->details->window == NULL) {
4320 		return NULL;
4321 	}
4322 	return nemo_window_get_ui_manager (view->details->window);
4323 }
4324 
4325 /**
4326  * nemo_view_get_model:
4327  *
4328  * Get the model for this NemoView.
4329  * @view: NemoView of interest.
4330  *
4331  * Return value: NemoDirectory for this view.
4332  *
4333  **/
4334 NemoDirectory *
nemo_view_get_model(NemoView * view)4335 nemo_view_get_model (NemoView *view)
4336 {
4337 	g_return_val_if_fail (NEMO_IS_VIEW (view), NULL);
4338 
4339 	return view->details->model;
4340 }
4341 
4342 GdkAtom
nemo_view_get_copied_files_atom(NemoView * view)4343 nemo_view_get_copied_files_atom (NemoView *view)
4344 {
4345 	g_return_val_if_fail (NEMO_IS_VIEW (view), GDK_NONE);
4346 
4347 	return copied_files_atom;
4348 }
4349 
4350 static void
prepend_uri_one(gpointer data,gpointer callback_data)4351 prepend_uri_one (gpointer data, gpointer callback_data)
4352 {
4353 	NemoFile *file;
4354 	GList **result;
4355 
4356 	g_assert (NEMO_IS_FILE (data));
4357 	g_assert (callback_data != NULL);
4358 
4359 	result = (GList **) callback_data;
4360 	file = (NemoFile *) data;
4361 	*result = g_list_prepend (*result, nemo_file_get_uri (file));
4362 }
4363 
4364 static void
offset_drop_points(GArray * relative_item_points,int x_offset,int y_offset)4365 offset_drop_points (GArray *relative_item_points,
4366 		    int x_offset, int y_offset)
4367 {
4368 	guint index;
4369 
4370 	if (relative_item_points == NULL) {
4371 		return;
4372 	}
4373 
4374 	for (index = 0; index < relative_item_points->len; index++) {
4375 		g_array_index (relative_item_points, GdkPoint, index).x += x_offset;
4376 		g_array_index (relative_item_points, GdkPoint, index).y += y_offset;
4377 	}
4378 }
4379 
4380 static void
nemo_view_create_links_for_files(NemoView * view,GList * files,GArray * relative_item_points)4381 nemo_view_create_links_for_files (NemoView *view, GList *files,
4382 				      GArray *relative_item_points)
4383 {
4384 	GList *uris;
4385 	char *dir_uri;
4386 	CopyMoveDoneData *copy_move_done_data;
4387 	g_assert (relative_item_points->len == 0
4388 		  || g_list_length (files) == relative_item_points->len);
4389 
4390         g_assert (NEMO_IS_VIEW (view));
4391         g_assert (files != NULL);
4392 
4393 	/* create a list of URIs */
4394 	uris = NULL;
4395 	g_list_foreach (files, prepend_uri_one, &uris);
4396 	uris = g_list_reverse (uris);
4397 
4398         g_assert (g_list_length (uris) == g_list_length (files));
4399 
4400 	/* offset the drop locations a bit so that we don't pile
4401 	 * up the icons on top of each other
4402 	 */
4403 	offset_drop_points (relative_item_points,
4404 			    DUPLICATE_HORIZONTAL_ICON_OFFSET,
4405 			    DUPLICATE_VERTICAL_ICON_OFFSET);
4406 
4407         copy_move_done_data = pre_copy_move (view);
4408 	dir_uri = nemo_view_get_backing_uri (view);
4409 	nemo_file_operations_copy_move (uris, relative_item_points, dir_uri, GDK_ACTION_LINK,
4410 					    GTK_WIDGET (view), copy_move_done_callback, copy_move_done_data);
4411 	g_free (dir_uri);
4412 	g_list_free_full (uris, g_free);
4413 }
4414 
4415 static void
nemo_view_duplicate_selection(NemoView * view,GList * files,GArray * relative_item_points)4416 nemo_view_duplicate_selection (NemoView *view, GList *files,
4417 				   GArray *relative_item_points)
4418 {
4419 	GList *uris;
4420 	CopyMoveDoneData *copy_move_done_data;
4421 
4422         g_assert (NEMO_IS_VIEW (view));
4423         g_assert (files != NULL);
4424 	g_assert (g_list_length (files) == relative_item_points->len
4425 		  || relative_item_points->len == 0);
4426 
4427 	/* create a list of URIs */
4428 	uris = NULL;
4429 	g_list_foreach (files, prepend_uri_one, &uris);
4430 	uris = g_list_reverse (uris);
4431 
4432         g_assert (g_list_length (uris) == g_list_length (files));
4433 
4434 	/* offset the drop locations a bit so that we don't pile
4435 	 * up the icons on top of each other
4436 	 */
4437 	offset_drop_points (relative_item_points,
4438 			    DUPLICATE_HORIZONTAL_ICON_OFFSET,
4439 			    DUPLICATE_VERTICAL_ICON_OFFSET);
4440 
4441         copy_move_done_data = pre_copy_move (view);
4442 	nemo_file_operations_copy_move (uris, relative_item_points, NULL, GDK_ACTION_COPY,
4443 					    GTK_WIDGET (view), copy_move_done_callback, copy_move_done_data);
4444 	g_list_free_full (uris, g_free);
4445 }
4446 
4447 /* special_link_in_selection
4448  *
4449  * Return TRUE if one of our special links is in the selection.
4450  * Special links include the following:
4451  *	 NEMO_DESKTOP_LINK_TRASH, NEMO_DESKTOP_LINK_HOME, NEMO_DESKTOP_LINK_MOUNT
4452  */
4453 
4454 static gboolean
special_link_in_selection(NemoView * view,GList * selection)4455 special_link_in_selection (NemoView *view, GList *selection)
4456 {
4457 	gboolean saw_link;
4458 	GList *node;
4459 	NemoFile *file;
4460 
4461 	g_return_val_if_fail (NEMO_IS_VIEW (view), FALSE);
4462 
4463 	saw_link = FALSE;
4464 
4465 	for (node = selection; node != NULL; node = node->next) {
4466 		file = NEMO_FILE (node->data);
4467 
4468 		saw_link = NEMO_IS_DESKTOP_ICON_FILE (file);
4469 
4470 		if (saw_link) {
4471 			break;
4472 		}
4473 	}
4474 
4475 	return saw_link;
4476 }
4477 
4478 /* desktop_or_home_dir_in_selection
4479  *
4480  * Return TRUE if either the desktop or the home directory is in the selection.
4481  */
4482 
4483 static gboolean
desktop_or_home_dir_in_selection(NemoView * view,GList * selection)4484 desktop_or_home_dir_in_selection (NemoView *view, GList *selection)
4485 {
4486 	gboolean saw_desktop_or_home_dir;
4487 	GList *node;
4488 	NemoFile *file;
4489 
4490 	g_return_val_if_fail (NEMO_IS_VIEW (view), FALSE);
4491 
4492 	saw_desktop_or_home_dir = FALSE;
4493 
4494 	for (node = selection; node != NULL; node = node->next) {
4495 		file = NEMO_FILE (node->data);
4496 
4497 		saw_desktop_or_home_dir =
4498 			nemo_file_is_home (file)
4499 			|| nemo_file_is_desktop_directory (file);
4500 
4501 		if (saw_desktop_or_home_dir) {
4502 			break;
4503 		}
4504 	}
4505 
4506 	return saw_desktop_or_home_dir;
4507 }
4508 
4509 /* directory_in_selection
4510  *
4511  * Return TRUE if selection contains a directory.
4512  */
4513 
4514 static gboolean
directory_in_selection(NemoView * view,GList * selection)4515 directory_in_selection (NemoView *view, GList *selection)
4516 {
4517     gboolean has_dir;
4518     GList *node;
4519     NemoFile *file;
4520 
4521     g_return_val_if_fail (NEMO_IS_VIEW (view), FALSE);
4522 
4523     has_dir = FALSE;
4524 
4525     for (node = selection; node != NULL; node = node->next) {
4526         file = NEMO_FILE (node->data);
4527 
4528         has_dir = nemo_file_is_directory (file);
4529         if (has_dir) {
4530             break;
4531         }
4532     }
4533 
4534     return has_dir;
4535 }
4536 
4537 static void
trash_or_delete_done_cb(GHashTable * debuting_uris,gboolean user_cancel,NemoView * view)4538 trash_or_delete_done_cb (GHashTable *debuting_uris,
4539 			 gboolean user_cancel,
4540 			 NemoView *view)
4541 {
4542 	if (user_cancel) {
4543 		view->details->selection_was_removed = FALSE;
4544 	}
4545 }
4546 
4547 static void
trash_or_delete_files(GtkWindow * parent_window,const GList * files,gboolean delete_if_all_already_in_trash,NemoView * view)4548 trash_or_delete_files (GtkWindow *parent_window,
4549 		       const GList *files,
4550 		       gboolean delete_if_all_already_in_trash,
4551 		       NemoView *view)
4552 {
4553 	GList *locations;
4554 	const GList *node;
4555 
4556 	locations = NULL;
4557 	for (node = files; node != NULL; node = node->next) {
4558 		locations = g_list_prepend (locations,
4559 					    nemo_file_get_location ((NemoFile *) node->data));
4560 	}
4561 
4562 	locations = g_list_reverse (locations);
4563 
4564 	nemo_file_operations_trash_or_delete (locations,
4565 						  parent_window,
4566 						  (NemoDeleteCallback) trash_or_delete_done_cb,
4567 						  view);
4568 	g_list_free_full (locations, g_object_unref);
4569 }
4570 
4571 static gboolean
can_rename_file(NemoView * view,NemoFile * file)4572 can_rename_file (NemoView *view, NemoFile *file)
4573 {
4574 	return nemo_file_can_rename (file);
4575 }
4576 
4577 gboolean
nemo_view_get_is_renaming(NemoView * view)4578 nemo_view_get_is_renaming (NemoView *view)
4579 {
4580 	return view->details->is_renaming;
4581 }
4582 
4583 void
nemo_view_set_is_renaming(NemoView * view,gboolean is_renaming)4584 nemo_view_set_is_renaming (NemoView *view,
4585 			       gboolean      is_renaming)
4586 {
4587 	view->details->is_renaming = is_renaming;
4588 }
4589 
4590 static void
start_renaming_file(NemoView * view,NemoFile * file,gboolean select_all)4591 start_renaming_file (NemoView *view,
4592 		     NemoFile *file,
4593 		     gboolean select_all)
4594 {
4595 	view->details->is_renaming = TRUE;
4596 
4597 	if (file !=  NULL) {
4598 		nemo_view_select_file (view, file);
4599 	}
4600 }
4601 
4602 static void
update_context_menu_position_from_event(NemoView * view,GdkEventButton * event)4603 update_context_menu_position_from_event (NemoView *view,
4604 					 GdkEventButton  *event)
4605 {
4606 	g_return_if_fail (NEMO_IS_VIEW (view));
4607 
4608 	if (event != NULL) {
4609 		view->details->context_menu_position.x = event->x;
4610 		view->details->context_menu_position.y = event->y;
4611 	} else {
4612 		view->details->context_menu_position.x = -1;
4613 		view->details->context_menu_position.y = -1;
4614 	}
4615 }
4616 
4617 /* handle the open command */
4618 
4619 static void
open_one_in_new_window(gpointer data,gpointer callback_data)4620 open_one_in_new_window (gpointer data, gpointer callback_data)
4621 {
4622 	g_assert (NEMO_IS_FILE (data));
4623 	g_assert (NEMO_IS_VIEW (callback_data));
4624 
4625 	nemo_view_activate_file (NEMO_VIEW (callback_data),
4626 				     NEMO_FILE (data),
4627 				     NEMO_WINDOW_OPEN_FLAG_NEW_WINDOW);
4628 }
4629 
4630 NemoFile *
nemo_view_get_directory_as_file(NemoView * view)4631 nemo_view_get_directory_as_file (NemoView *view)
4632 {
4633 	g_assert (NEMO_IS_VIEW (view));
4634 
4635 	return view->details->directory_as_file;
4636 }
4637 
4638 static void
open_with_launch_application_callback(GtkAction * action,gpointer callback_data)4639 open_with_launch_application_callback (GtkAction *action,
4640 				       gpointer callback_data)
4641 {
4642 	ApplicationLaunchParameters *launch_parameters;
4643 
4644 	launch_parameters = (ApplicationLaunchParameters *) callback_data;
4645 	nemo_launch_application
4646 		(launch_parameters->application,
4647 		 launch_parameters->files,
4648 		 nemo_view_get_containing_window (launch_parameters->directory_view));
4649 }
4650 
4651 static char *
escape_action_name(const char * action_name,const char * prefix)4652 escape_action_name (const char *action_name,
4653 		    const char *prefix)
4654 {
4655 	GString *s;
4656 
4657 	if (action_name == NULL) {
4658 		return NULL;
4659 	}
4660 
4661 	s = g_string_new (prefix);
4662 
4663 	while (*action_name != 0) {
4664 		switch (*action_name) {
4665 		case '\\':
4666 			g_string_append (s, "\\\\");
4667 			break;
4668 		case '/':
4669 			g_string_append (s, "\\s");
4670 			break;
4671 		case '&':
4672 			g_string_append (s, "\\a");
4673 			break;
4674 		case '"':
4675 			g_string_append (s, "\\q");
4676 			break;
4677 		default:
4678 			g_string_append_c (s, *action_name);
4679 		}
4680 
4681 		action_name ++;
4682 	}
4683 	return g_string_free (s, FALSE);
4684 }
4685 
4686 static char *
escape_action_path(const char * action_path)4687 escape_action_path (const char *action_path)
4688 {
4689 	GString *s;
4690 
4691 	if (action_path == NULL) {
4692 		return NULL;
4693 	}
4694 
4695 	s = g_string_sized_new (strlen (action_path) + 2);
4696 
4697 	while (*action_path != 0) {
4698 		switch (*action_path) {
4699 		case '\\':
4700 			g_string_append (s, "\\\\");
4701 			break;
4702 		case '&':
4703 			g_string_append (s, "\\a");
4704 			break;
4705 		case '"':
4706 			g_string_append (s, "\\q");
4707 			break;
4708 		default:
4709 			g_string_append_c (s, *action_path);
4710 		}
4711 
4712 		action_path ++;
4713 	}
4714 	return g_string_free (s, FALSE);
4715 }
4716 
4717 
4718 static void
add_submenu(GtkUIManager * ui_manager,GtkActionGroup * action_group,guint merge_id,const char * parent_path,const char * uri,const char * label,GdkPixbuf * pixbuf,gboolean add_action)4719 add_submenu (GtkUIManager *ui_manager,
4720 	     GtkActionGroup *action_group,
4721 	     guint merge_id,
4722 	     const char *parent_path,
4723 	     const char *uri,
4724 	     const char *label,
4725 	     GdkPixbuf *pixbuf,
4726 	     gboolean add_action)
4727 {
4728 	char *escaped_label;
4729 	char *action_name;
4730 	char *submenu_name;
4731 	char *escaped_submenu_name;
4732 	GtkAction *action;
4733 
4734 	if (parent_path != NULL) {
4735 		action_name = escape_action_name (uri, "submenu_");
4736 		submenu_name = g_path_get_basename (uri);
4737 		escaped_submenu_name = escape_action_path (submenu_name);
4738 		escaped_label = eel_str_double_underscores (label);
4739 
4740 		if (add_action) {
4741 			action = gtk_action_new (action_name,
4742 						 escaped_label,
4743 						 NULL,
4744 						 NULL);
4745 			if (pixbuf != NULL) {
4746 				gtk_action_set_gicon (action, G_ICON (pixbuf));
4747 			}
4748 
4749 			g_object_set (action, "hide-if-empty", FALSE, NULL);
4750 
4751 			gtk_action_group_add_action (action_group,
4752 						     action);
4753 			g_object_unref (action);
4754 		}
4755 
4756 		gtk_ui_manager_add_ui (ui_manager,
4757 				       merge_id,
4758 				       parent_path,
4759 				       escaped_submenu_name,
4760 				       action_name,
4761 				       GTK_UI_MANAGER_MENU,
4762 				       FALSE);
4763 		g_free (action_name);
4764 		g_free (escaped_label);
4765 		g_free (submenu_name);
4766 		g_free (escaped_submenu_name);
4767 	}
4768 }
4769 
4770 static void
menu_item_show_image(GtkUIManager * ui_manager,const char * parent_path,const char * action_name,gboolean ignore_gtk_pref)4771 menu_item_show_image (GtkUIManager *ui_manager,
4772 		      const char   *parent_path,
4773 		      const char   *action_name,
4774                 gboolean    ignore_gtk_pref)
4775 {
4776     GtkImageMenuItem *menuitem;
4777     char *path;
4778     gboolean show = TRUE;
4779 
4780     path = g_strdup_printf ("%s/%s", parent_path, action_name);
4781     menuitem = GTK_IMAGE_MENU_ITEM (gtk_ui_manager_get_widget (ui_manager,
4782                                                                path));
4783     g_free (path);
4784 
4785     if (!ignore_gtk_pref) {
4786         g_object_get (gtk_settings_get_default (), "gtk-menu-images", &show, NULL);
4787 
4788         if (!show && !gtk_image_menu_item_get_always_show_image (menuitem)) {
4789             return;
4790         }
4791     }
4792 
4793     if (menuitem != NULL) {
4794         gtk_image_menu_item_set_always_show_image (menuitem, show);
4795     }
4796 }
4797 
4798 static void
add_application_to_open_with_menu(NemoView * view,GAppInfo * application,GList * files,int index,const char * menu_placeholder,const char * popup_placeholder,const gboolean submenu)4799 add_application_to_open_with_menu (NemoView *view,
4800 				   GAppInfo *application,
4801 				   GList *files,
4802 				   int index,
4803 				   const char *menu_placeholder,
4804 				   const char *popup_placeholder,
4805 				   const gboolean submenu)
4806 {
4807 	ApplicationLaunchParameters *launch_parameters;
4808 	char *tip;
4809 	char *label;
4810 	char *action_name;
4811 	char *escaped_app;
4812 	GtkAction *action;
4813 	GIcon *app_icon;
4814 	GtkUIManager *ui_manager;
4815 
4816 	launch_parameters = application_launch_parameters_new
4817 		(application, files, view);
4818 	escaped_app = eel_str_double_underscores (g_app_info_get_name (application));
4819 	if (submenu)
4820 		label = g_strdup_printf ("%s", escaped_app);
4821 	else
4822 		label = g_strdup_printf (_("Open With %s"), escaped_app);
4823 
4824 	tip = g_strdup_printf (ngettext ("Use \"%s\" to open the selected item",
4825 					 "Use \"%s\" to open the selected items",
4826 					 g_list_length (files)),
4827 			       escaped_app);
4828 	g_free (escaped_app);
4829 
4830 	action_name = g_strdup_printf ("open_with_%d", index);
4831 
4832 	action = gtk_action_new (action_name,
4833 				 label,
4834 				 tip,
4835 				 NULL);
4836 
4837 	app_icon = g_app_info_get_icon (application);
4838 	if (app_icon != NULL) {
4839 		g_object_ref (app_icon);
4840 	} else {
4841 		app_icon = g_themed_icon_new ("application-x-executable");
4842 	}
4843 
4844 	gtk_action_set_gicon (action, app_icon);
4845 	g_object_unref (app_icon);
4846 
4847 	g_signal_connect_data (action, "activate",
4848 			       G_CALLBACK (open_with_launch_application_callback),
4849 			       launch_parameters,
4850 			       (GClosureNotify)application_launch_parameters_free, 0);
4851 
4852 	gtk_action_group_add_action (view->details->open_with_action_group,
4853 				     action);
4854 	g_object_unref (action);
4855 
4856 	ui_manager = nemo_window_get_ui_manager (view->details->window);
4857 	gtk_ui_manager_add_ui (ui_manager,
4858 			       view->details->open_with_merge_id,
4859 			       menu_placeholder,
4860 			       action_name,
4861 			       action_name,
4862 			       GTK_UI_MANAGER_MENUITEM,
4863 			       FALSE);
4864 
4865 	menu_item_show_image (ui_manager, menu_placeholder, action_name, TRUE);
4866 
4867 	gtk_ui_manager_add_ui (ui_manager,
4868 			       view->details->open_with_merge_id,
4869 			       popup_placeholder,
4870 			       action_name,
4871 			       action_name,
4872 			       GTK_UI_MANAGER_MENUITEM,
4873 			       FALSE);
4874 
4875 	menu_item_show_image (ui_manager, popup_placeholder, action_name, TRUE);
4876 
4877 	g_free (action_name);
4878 	g_free (label);
4879 	g_free (tip);
4880 }
4881 
4882 static void
get_x_content_async_callback(const char ** content,gpointer user_data)4883 get_x_content_async_callback (const char **content,
4884 			      gpointer user_data)
4885 {
4886 	NemoView *view;
4887 
4888 	view = NEMO_VIEW (user_data);
4889 
4890 	if (view->details->window != NULL) {
4891 		schedule_update_menus (view);
4892 	}
4893 	g_object_unref (view);
4894 }
4895 
4896 static void
add_x_content_apps(NemoView * view,NemoFile * file,GList ** applications)4897 add_x_content_apps (NemoView *view, NemoFile *file, GList **applications)
4898 {
4899 	GMount *mount;
4900 	char **x_content_types;
4901 	unsigned int n;
4902 
4903 	g_return_if_fail (applications != NULL);
4904 
4905 	mount = nemo_file_get_mount (file);
4906 
4907 	if (mount == NULL) {
4908 		return;
4909 	}
4910 
4911 	x_content_types = nemo_get_cached_x_content_types_for_mount (mount);
4912 	if (x_content_types != NULL) {
4913 		for (n = 0; x_content_types[n] != NULL; n++) {
4914 			char *x_content_type = x_content_types[n];
4915 			GList *app_info_for_x_content_type;
4916 
4917 			app_info_for_x_content_type = g_app_info_get_all_for_type (x_content_type);
4918 			*applications = g_list_concat (*applications, app_info_for_x_content_type);
4919 		}
4920 		g_strfreev (x_content_types);
4921 	} else {
4922 		nemo_get_x_content_types_for_mount_async (mount,
4923 							      get_x_content_async_callback,
4924 							      NULL,
4925 							      g_object_ref (view));
4926 
4927 	}
4928 
4929 	g_object_unref (mount);
4930 }
4931 
4932 static void
reset_open_with_menu(NemoView * view,GList * selection,gboolean filter_default)4933 reset_open_with_menu (NemoView *view, GList *selection, gboolean filter_default)
4934 {
4935 	GList *applications, *node;
4936 	NemoFile *file;
4937 	gboolean submenu_visible;
4938 	int num_applications;
4939 	int index;
4940 	gboolean other_applications_visible;
4941 	gboolean open_with_chooser_visible;
4942 	GtkUIManager *ui_manager;
4943 	GtkAction *action;
4944 	GAppInfo *default_app;
4945 
4946 	/* Clear any previous inserted items in the applications and viewers placeholders */
4947 
4948 	ui_manager = nemo_window_get_ui_manager (view->details->window);
4949 	nemo_ui_unmerge_ui (ui_manager,
4950 				&view->details->open_with_merge_id,
4951 				&view->details->open_with_action_group);
4952 
4953 	nemo_ui_prepare_merge_ui (ui_manager,
4954 				      "OpenWithGroup",
4955 				      &view->details->open_with_merge_id,
4956 				      &view->details->open_with_action_group);
4957 
4958 	other_applications_visible = (selection != NULL);
4959 
4960 	for (node = selection; node != NULL; node = node->next) {
4961 
4962 		file = NEMO_FILE (node->data);
4963 
4964 		other_applications_visible &= (!nemo_mime_file_opens_in_view (file) ||
4965                                         nemo_file_is_directory (file));
4966 	}
4967 
4968 	default_app = NULL;
4969 	if (filter_default && selection != NULL) {
4970 		default_app = nemo_mime_get_default_application_for_files (selection);
4971 	}
4972 
4973 	applications = NULL;
4974 	if (other_applications_visible) {
4975 		applications = nemo_mime_get_applications_for_files (selection);
4976 	}
4977 
4978 	if (g_list_length (selection) == 1) {
4979 		add_x_content_apps (view, NEMO_FILE (selection->data), &applications);
4980 	}
4981 
4982 
4983 	num_applications = g_list_length (applications);
4984 
4985 	if (file_list_all_are_folders (selection)) {
4986 		submenu_visible = (num_applications > 0);
4987 	} else {
4988 		submenu_visible = (num_applications > 1);
4989 	}
4990 
4991 	for (node = applications, index = 0; node != NULL; node = node->next, index++) {
4992 		GAppInfo *application;
4993 		char *menu_path;
4994 		char *popup_path;
4995 
4996 		application = node->data;
4997 
4998 		if (default_app != NULL && g_app_info_equal (default_app, application)) {
4999 			continue;
5000 		}
5001 
5002 		if (submenu_visible) {
5003 			menu_path = (char *)NEMO_VIEW_MENU_PATH_APPLICATIONS_SUBMENU_PLACEHOLDER;
5004 			popup_path = (char *)NEMO_VIEW_POPUP_PATH_APPLICATIONS_SUBMENU_PLACEHOLDER;
5005 		} else {
5006 			menu_path = (char *)NEMO_VIEW_MENU_PATH_APPLICATIONS_PLACEHOLDER;
5007 			popup_path = (char *)NEMO_VIEW_POPUP_PATH_APPLICATIONS_PLACEHOLDER;
5008 		}
5009 
5010 		gtk_ui_manager_add_ui (nemo_window_get_ui_manager (view->details->window),
5011 				       view->details->open_with_merge_id,
5012 				       menu_path,
5013 				       "separator",
5014 				       NULL,
5015 				       GTK_UI_MANAGER_SEPARATOR,
5016 				       FALSE);
5017 
5018 		add_application_to_open_with_menu (view,
5019 						   node->data,
5020 						   selection,
5021 						   index,
5022 						   menu_path, popup_path, submenu_visible);
5023 	}
5024 	g_list_free_full (applications, g_object_unref);
5025 	if (default_app != NULL) {
5026 		g_object_unref (default_app);
5027 	}
5028 
5029 	open_with_chooser_visible = other_applications_visible &&
5030 		g_list_length (selection) == 1;
5031 
5032 	if (submenu_visible) {
5033 		action = gtk_action_group_get_action (view->details->dir_action_group,
5034 						      NEMO_ACTION_OTHER_APPLICATION1);
5035 		gtk_action_set_visible (action, open_with_chooser_visible);
5036 		action = gtk_action_group_get_action (view->details->dir_action_group,
5037 						      NEMO_ACTION_OTHER_APPLICATION2);
5038 		gtk_action_set_visible (action, FALSE);
5039 	} else {
5040 		action = gtk_action_group_get_action (view->details->dir_action_group,
5041 						      NEMO_ACTION_OTHER_APPLICATION1);
5042 		gtk_action_set_visible (action, FALSE);
5043 		action = gtk_action_group_get_action (view->details->dir_action_group,
5044 						      NEMO_ACTION_OTHER_APPLICATION2);
5045 		gtk_action_set_visible (action, open_with_chooser_visible);
5046 	}
5047 }
5048 
5049 static void
move_copy_selection_to_location(NemoView * view,int copy_action,char * target_uri)5050 move_copy_selection_to_location (NemoView *view,
5051                  int copy_action,
5052                  char *target_uri)
5053 {
5054     GList *selection, *uris, *l;
5055 
5056     selection = nemo_view_get_selection_for_file_transfer (view);
5057     if (selection == NULL) {
5058         return;
5059     }
5060 
5061     uris = NULL;
5062     for (l = selection; l != NULL; l = l->next) {
5063         uris = g_list_prepend (uris,
5064                        nemo_file_get_uri ((NemoFile *) l->data));
5065     }
5066     uris = g_list_reverse (uris);
5067 
5068     nemo_view_move_copy_items (view, uris, NULL, target_uri,
5069                        copy_action,
5070                        0, 0);
5071 
5072     g_list_free_full (uris, g_free);
5073     nemo_file_list_free (selection);
5074 }
5075 
5076 static void
action_move_bookmark_callback(GtkAction * action,gpointer callback_data)5077 action_move_bookmark_callback (GtkAction *action, gpointer callback_data)
5078 {
5079     NemoView *view;
5080     BookmarkCallbackData *data;
5081 
5082     data = (BookmarkCallbackData *) callback_data;
5083     view = NEMO_VIEW(data->view);
5084     move_copy_selection_to_location (view, GDK_ACTION_MOVE, data->dest_uri);
5085 }
5086 
5087 static void
action_copy_bookmark_callback(GtkAction * action,gpointer callback_data)5088 action_copy_bookmark_callback (GtkAction *action, gpointer callback_data)
5089 {
5090     NemoView *view;
5091     BookmarkCallbackData *data;
5092 
5093     data = (BookmarkCallbackData *) callback_data;
5094     view = NEMO_VIEW(data->view);
5095     move_copy_selection_to_location (view, GDK_ACTION_COPY, data->dest_uri);
5096 }
5097 
5098 static void
setup_bookmark_action(char * action_name,const char * bookmark_name,const char * icon_name,char * mount_uri,GtkUIManager * ui_manager,gboolean move,GtkActionGroup * action_group,gint merge_id,const char * path,NemoView * view)5099 setup_bookmark_action(      char *action_name,
5100                       const char *bookmark_name,
5101                       const char *icon_name,
5102                             char *mount_uri,
5103                     GtkUIManager *ui_manager,
5104                          gboolean move,
5105                   GtkActionGroup *action_group,
5106                              gint merge_id,
5107                             const char *path,
5108                         NemoView *view)
5109 {
5110 
5111     GtkAction *action;
5112     action = gtk_action_new (action_name,
5113              bookmark_name,
5114              NULL,
5115              NULL);
5116     gtk_action_set_icon_name (action, icon_name);
5117 
5118     if (move) {
5119         g_signal_connect_data (action, "activate",
5120                G_CALLBACK (action_move_bookmark_callback),
5121                bookmark_callback_data_new(view, mount_uri),
5122                (GClosureNotify)bookmark_callback_data_free, 0);
5123     } else {
5124         g_signal_connect_data (action, "activate",
5125                G_CALLBACK (action_copy_bookmark_callback),
5126                bookmark_callback_data_new(view, mount_uri),
5127                (GClosureNotify)bookmark_callback_data_free, 0);
5128     }
5129 
5130     gtk_action_group_add_action (action_group, action);
5131 
5132     gtk_ui_manager_add_ui ( ui_manager,
5133                             merge_id,
5134                             path,
5135                             action_name,
5136                             action_name,
5137                             GTK_UI_MANAGER_MENUITEM,
5138                             FALSE);
5139     g_object_unref (action);
5140     g_free (action_name);
5141 }
5142 
5143 static void
add_bookmark_to_action(NemoView * view,const gchar * bookmark_name,const gchar * icon_name,gchar * mount_uri,gint index)5144 add_bookmark_to_action (NemoView *view, const gchar *bookmark_name, const gchar *icon_name, gchar *mount_uri, gint index)
5145 {
5146     GtkUIManager *ui_manager;
5147     ui_manager = nemo_window_get_ui_manager (view->details->window);
5148 
5149     setup_bookmark_action(g_strdup_printf ("BM_MOVETO_POPUP_%d", index),
5150                                             bookmark_name,
5151                                             icon_name,
5152                                             mount_uri,
5153                                             ui_manager,
5154                                             TRUE,
5155                                             view->details->copy_move_action_groups[0],
5156                                             view->details->copy_move_merge_ids[0],
5157                                             NEMO_VIEW_POPUP_PATH_BOOKMARK_MOVETO_ENTRIES_PLACEHOLDER,
5158                                             view);
5159 
5160     setup_bookmark_action(g_strdup_printf ("BM_COPYTO_POPUP_%d", index),
5161                                             bookmark_name,
5162                                             icon_name,
5163                                             mount_uri,
5164                                             ui_manager,
5165                                             FALSE,
5166                                             view->details->copy_move_action_groups[1],
5167                                             view->details->copy_move_merge_ids[1],
5168                                             NEMO_VIEW_POPUP_PATH_BOOKMARK_COPYTO_ENTRIES_PLACEHOLDER,
5169                                             view);
5170 
5171     setup_bookmark_action(g_strdup_printf ("BM_MOVETO_MENU_%d", index),
5172                                             bookmark_name,
5173                                             icon_name,
5174                                             mount_uri,
5175                                             ui_manager,
5176                                             TRUE,
5177                                             view->details->copy_move_action_groups[2],
5178                                             view->details->copy_move_merge_ids[2],
5179                                             NEMO_VIEW_MENU_PATH_BOOKMARK_MOVETO_ENTRIES_PLACEHOLDER,
5180                                             view);
5181 
5182     setup_bookmark_action(g_strdup_printf ("BM_COPYTO_MENU_%d", index),
5183                                             bookmark_name,
5184                                             icon_name,
5185                                             mount_uri,
5186                                             ui_manager,
5187                                             FALSE,
5188                                             view->details->copy_move_action_groups[3],
5189                                             view->details->copy_move_merge_ids[3],
5190                                             NEMO_VIEW_MENU_PATH_BOOKMARK_COPYTO_ENTRIES_PLACEHOLDER,
5191                                             view);
5192 }
5193 
5194 static void
add_place_to_action(NemoView * view,const gchar * bookmark_name,const gchar * icon_name,gchar * mount_uri,gint index)5195 add_place_to_action (NemoView *view, const gchar *bookmark_name, const gchar *icon_name, gchar *mount_uri, gint index)
5196 {
5197     GtkUIManager *ui_manager;
5198     ui_manager = nemo_window_get_ui_manager (view->details->window);
5199 
5200     setup_bookmark_action(g_strdup_printf ("PLACE_MOVETO_POPUP_%d", index),
5201                                             bookmark_name,
5202                                             icon_name,
5203                                             mount_uri,
5204                                             ui_manager,
5205                                             TRUE,
5206                                             view->details->copy_move_action_groups[0],
5207                                             view->details->copy_move_merge_ids[0],
5208                                             NEMO_VIEW_POPUP_PATH_PLACES_MOVETO_ENTRIES_PLACEHOLDER,
5209                                             view);
5210 
5211     setup_bookmark_action(g_strdup_printf ("PLACE_COPYTO_POPUP_%d", index),
5212                                             bookmark_name,
5213                                             icon_name,
5214                                             mount_uri,
5215                                             ui_manager,
5216                                             FALSE,
5217                                             view->details->copy_move_action_groups[1],
5218                                             view->details->copy_move_merge_ids[1],
5219                                             NEMO_VIEW_POPUP_PATH_PLACES_COPYTO_ENTRIES_PLACEHOLDER,
5220                                             view);
5221 
5222     setup_bookmark_action(g_strdup_printf ("PLACE_MOVETO_MENU_%d", index),
5223                                             bookmark_name,
5224                                             icon_name,
5225                                             mount_uri,
5226                                             ui_manager,
5227                                             TRUE,
5228                                             view->details->copy_move_action_groups[2],
5229                                             view->details->copy_move_merge_ids[2],
5230                                             NEMO_VIEW_MENU_PATH_PLACES_MOVETO_ENTRIES_PLACEHOLDER,
5231                                             view);
5232 
5233     setup_bookmark_action(g_strdup_printf ("PLACE_COPYTO_MENU_%d", index),
5234                                             bookmark_name,
5235                                             icon_name,
5236                                             mount_uri,
5237                                             ui_manager,
5238                                             FALSE,
5239                                             view->details->copy_move_action_groups[3],
5240                                             view->details->copy_move_merge_ids[3],
5241                                             NEMO_VIEW_MENU_PATH_PLACES_COPYTO_ENTRIES_PLACEHOLDER,
5242                                             view);
5243 }
5244 
5245 static void
reset_move_copy_to_menu(NemoView * view)5246 reset_move_copy_to_menu (NemoView *view)
5247 {
5248     NemoBookmark *bookmark;
5249     NemoFile *file;
5250     int bookmark_count, index;
5251     GtkUIManager *ui_manager;
5252     GFile *root;
5253     const gchar *bookmark_name;
5254     gchar *icon_name;
5255     char *mount_uri;
5256 
5257     ui_manager = nemo_window_get_ui_manager (view->details->window);
5258 
5259     int i;
5260 
5261     for (i = 0; i < 4; i++) {
5262         nemo_ui_unmerge_ui (ui_manager,
5263                 &view->details->copy_move_merge_ids[i],
5264                 &view->details->copy_move_action_groups[i]);
5265         gchar *id = g_strdup_printf ("MoveCopyMenuGroup_%d", i);
5266         nemo_ui_prepare_merge_ui (ui_manager,
5267                                   id,
5268                                   &view->details->copy_move_merge_ids[i],
5269                                   &view->details->copy_move_action_groups[i]);
5270         g_free (id);
5271     }
5272 
5273     GtkAction *action;
5274 
5275     mount_uri = nemo_get_home_directory_uri ();
5276     file = nemo_file_get_by_uri (mount_uri);
5277     g_free (mount_uri);
5278 
5279     icon_name = nemo_file_get_control_icon_name (file);
5280 
5281     action = gtk_action_group_get_action (view->details->dir_action_group, NEMO_ACTION_COPY_TO_HOME);
5282     gtk_action_set_icon_name (action, icon_name);
5283 
5284     action = gtk_action_group_get_action (view->details->dir_action_group, NEMO_ACTION_MOVE_TO_HOME);
5285     gtk_action_set_icon_name (action, icon_name);
5286 
5287     g_clear_pointer (&icon_name, g_free);
5288     g_object_unref (file);
5289 
5290     mount_uri = nemo_get_desktop_directory_uri ();
5291     file = nemo_file_get_by_uri (mount_uri);
5292     g_free (mount_uri);
5293 
5294     icon_name = nemo_file_get_control_icon_name (file);
5295 
5296     action = gtk_action_group_get_action (view->details->dir_action_group, NEMO_ACTION_COPY_TO_DESKTOP);
5297     gtk_action_set_icon_name (action, icon_name);
5298 
5299     action = gtk_action_group_get_action (view->details->dir_action_group, NEMO_ACTION_MOVE_TO_DESKTOP);
5300     gtk_action_set_icon_name (action, icon_name);
5301 
5302     g_clear_pointer (&icon_name, g_free);
5303     g_object_unref (file);
5304 
5305     if (view->details->showing_bookmarks_in_to_menus) {
5306         bookmark_count = nemo_bookmark_list_length (view->details->bookmarks);
5307         for (index = 0; index < bookmark_count; ++index) {
5308             bookmark = nemo_bookmark_list_item_at (view->details->bookmarks, index);
5309 
5310             /* Unlike the sidebar or the bookmarks menu, we are using bookmarks as
5311                file operation targets, not locations to open.  As such, we should
5312                never show unmounted/invalid locations in the move-to/copy-to menu */
5313             if (!nemo_bookmark_uri_get_exists (bookmark)) {
5314                 continue;
5315             }
5316 
5317             root = nemo_bookmark_get_location (bookmark);
5318             file = nemo_file_get (root);
5319 
5320             nemo_file_unref (file);
5321 
5322             bookmark_name = nemo_bookmark_get_name (bookmark);
5323             icon_name = nemo_bookmark_get_icon_name (bookmark);
5324             mount_uri = nemo_bookmark_get_uri (bookmark);
5325 
5326             add_bookmark_to_action (view,
5327                                     bookmark_name,
5328                                     icon_name,
5329                                     mount_uri,
5330                                     index);
5331 
5332             g_object_unref (root);
5333             g_free (icon_name);
5334             g_free (mount_uri);
5335         }
5336     }
5337 
5338     if (view->details->showing_places_in_to_menus) {
5339 
5340         GList *mounts, *l, *ll, *drives, *volumes;
5341         GVolumeMonitor *volume_monitor;
5342         GMount *mount;
5343         GVolume *volume;
5344         GDrive *drive;
5345         GList *network_mounts = NULL;
5346         GList *network_volumes = NULL;
5347         gchar *name, *identifier;
5348         index = 0;
5349 
5350         /* add mounts that has no volume (/etc/mtab mounts, ftp, sftp,...) */
5351         volume_monitor = g_volume_monitor_get ();
5352         mounts = g_volume_monitor_get_mounts (volume_monitor);
5353 
5354         for (l = mounts; l != NULL; l = l->next) {
5355             mount = l->data;
5356             if (g_mount_is_shadowed (mount)) {
5357                 g_object_unref (mount);
5358                 continue;
5359             }
5360             volume = g_mount_get_volume (mount);
5361             if (volume != NULL) {
5362                     g_object_unref (volume);
5363                 g_object_unref (mount);
5364                 continue;
5365             }
5366             root = g_mount_get_default_location (mount);
5367 
5368             if (!g_file_is_native (root)) {
5369                 gboolean really_network = TRUE;
5370                 gchar *path = g_file_get_path (root);
5371                 if (!path) {
5372                     network_mounts = g_list_prepend (network_mounts, mount);
5373                     g_object_unref (root);
5374                     continue;
5375                 }
5376                 gchar *escaped1 = g_uri_unescape_string (path, "");
5377                 gchar *escaped2 = g_uri_unescape_string (escaped1, "");
5378                 gchar *ptr = g_strrstr (escaped2, "file://");
5379                 if (ptr != NULL) {
5380                     GFile *actual_file = g_file_new_for_uri (ptr);
5381                     if (g_file_is_native(actual_file)) {
5382                         really_network = FALSE;
5383                     }
5384                     g_object_unref(actual_file);
5385                 }
5386                 g_free (path);
5387                 g_free (escaped1);
5388                 g_free (escaped2);
5389                 if (really_network) {
5390                     network_mounts = g_list_prepend (network_mounts, mount);
5391                     g_object_unref (root);
5392                     continue;
5393                 }
5394             }
5395 
5396             icon_name = nemo_get_mount_icon_name (mount);
5397             mount_uri = g_file_get_uri (root);
5398             name = g_mount_get_name (mount);
5399 
5400             add_place_to_action (view,
5401                                  name,
5402                                  icon_name,
5403                                  mount_uri,
5404                                  index);
5405 
5406             g_object_unref (root);
5407             g_object_unref (mount);
5408             g_free (icon_name);
5409             g_free (name);
5410             g_free (mount_uri);
5411 
5412             index++;
5413         }
5414         g_list_free (mounts);
5415 
5416         /* first go through all connected drives */
5417         drives = g_volume_monitor_get_connected_drives (volume_monitor);
5418 
5419         for (l = drives; l != NULL; l = l->next) {
5420             drive = l->data;
5421 
5422             volumes = g_drive_get_volumes (drive);
5423             if (volumes != NULL) {
5424                 for (ll = volumes; ll != NULL; ll = ll->next) {
5425                     volume = ll->data;
5426                     identifier = g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_CLASS);
5427 
5428                     if (g_strcmp0 (identifier, "network") == 0) {
5429                         g_free (identifier);
5430                         network_volumes = g_list_prepend (network_volumes, volume);
5431                         continue;
5432                     }
5433                     g_free (identifier);
5434 
5435                     mount = g_volume_get_mount (volume);
5436                     if (mount != NULL) {
5437                         /* Show mounted volume in the sidebar */
5438                         icon_name = nemo_get_mount_icon_name (mount);
5439                         root = g_mount_get_default_location (mount);
5440                         mount_uri = g_file_get_uri (root);
5441                         name = g_mount_get_name (mount);
5442 
5443                         add_place_to_action (view,
5444                                              name,
5445                                              icon_name,
5446                                              mount_uri,
5447                                              index);
5448 
5449                         g_object_unref (root);
5450                         g_object_unref (mount);
5451                         g_free (icon_name);
5452                         g_free (name);
5453                         g_free (mount_uri);
5454                         index++;
5455                     }
5456                     g_object_unref (volume);
5457                 }
5458                 g_list_free (volumes);
5459             }
5460             g_object_unref (drive);
5461         }
5462         g_list_free (drives);
5463 
5464         /* add all volumes that is not associated with a drive */
5465         volumes = g_volume_monitor_get_volumes (volume_monitor);
5466         for (l = volumes; l != NULL; l = l->next) {
5467             volume = l->data;
5468             drive = g_volume_get_drive (volume);
5469             if (drive != NULL) {
5470                     g_object_unref (volume);
5471                 g_object_unref (drive);
5472                 continue;
5473             }
5474 
5475             identifier = g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_CLASS);
5476 
5477             if (g_strcmp0 (identifier, "network") == 0) {
5478                 g_free (identifier);
5479                 network_volumes = g_list_prepend (network_volumes, volume);
5480                 continue;
5481             }
5482             g_free (identifier);
5483 
5484             mount = g_volume_get_mount (volume);
5485             if (mount != NULL) {
5486                 icon_name = nemo_get_mount_icon_name (mount);
5487                 root = g_mount_get_default_location (mount);
5488                 mount_uri = g_file_get_uri (root);
5489 
5490                 g_object_unref (root);
5491                 name = g_mount_get_name (mount);
5492 
5493                 add_place_to_action (view,
5494                                      name,
5495                                      icon_name,
5496                                      mount_uri,
5497                                      index);
5498 
5499                 g_object_unref (mount);
5500                 g_free (icon_name);
5501                 g_free (name);
5502                 g_free (mount_uri);
5503                 index++;
5504             }
5505             g_object_unref (volume);
5506         }
5507         g_list_free (volumes);
5508         g_object_unref (volume_monitor);
5509 
5510         network_volumes = g_list_reverse (network_volumes);
5511         for (l = network_volumes; l != NULL; l = l->next) {
5512             volume = l->data;
5513             mount = g_volume_get_mount (volume);
5514 
5515             if (mount != NULL) {
5516                 network_mounts = g_list_prepend (network_mounts, mount);
5517                 continue;
5518             }
5519         }
5520 
5521         g_list_free_full (network_volumes, g_object_unref);
5522 
5523         network_mounts = g_list_reverse (network_mounts);
5524         for (l = network_mounts; l != NULL; l = l->next) {
5525             mount = l->data;
5526             root = g_mount_get_default_location (mount);
5527             icon_name = nemo_get_mount_icon_name (mount);
5528             mount_uri = g_file_get_uri (root);
5529             name = g_mount_get_name (mount);
5530 
5531             add_place_to_action (view,
5532                                  name,
5533                                  icon_name,
5534                                  mount_uri,
5535                                  index);
5536 
5537             g_object_unref (root);
5538             g_free (icon_name);
5539             g_free (name);
5540             g_free (mount_uri);
5541             index++;
5542         }
5543 
5544         g_list_free_full (network_mounts, g_object_unref);
5545     }
5546 }
5547 
5548 static void
disconnect_bookmark(gpointer data,gpointer callback_data)5549 disconnect_bookmark (gpointer data, gpointer callback_data)
5550 {
5551     GtkAction *action = GTK_ACTION (data);
5552     g_signal_handlers_disconnect_matched (action,
5553                           G_SIGNAL_MATCH_FUNC, 0, 0,
5554                           NULL, action_move_bookmark_callback, NULL);
5555     g_signal_handlers_disconnect_matched (action,
5556                           G_SIGNAL_MATCH_FUNC, 0, 0,
5557                           NULL, action_copy_bookmark_callback, NULL);
5558 }
5559 
5560 static void
disconnect_bookmark_signals(NemoView * view)5561 disconnect_bookmark_signals (NemoView *view)
5562 {
5563     int i;
5564     GList *list;
5565     GtkActionGroup *group;
5566     for (i = 0; i < 4; i++) {
5567         group = GTK_ACTION_GROUP (view->details->copy_move_action_groups[i]);
5568         list = gtk_action_group_list_actions (group);
5569         g_list_foreach (list, disconnect_bookmark, NULL);
5570         g_list_free (list);
5571     }
5572 }
5573 
5574 static GList *
get_all_extension_menu_items(GtkWidget * window,GList * selection)5575 get_all_extension_menu_items (GtkWidget *window,
5576 			      GList *selection)
5577 {
5578 	GList *items;
5579 	GList *providers;
5580 	GList *l;
5581 
5582 	providers = nemo_module_get_extensions_for_type (NEMO_TYPE_MENU_PROVIDER);
5583 	items = NULL;
5584 
5585 	for (l = providers; l != NULL; l = l->next) {
5586 		NemoMenuProvider *provider;
5587 		GList *file_items;
5588 
5589 		provider = NEMO_MENU_PROVIDER (l->data);
5590 		file_items = nemo_menu_provider_get_file_items (provider,
5591 								    window,
5592 								    selection);
5593 		items = g_list_concat (items, file_items);
5594 	}
5595 
5596 	nemo_module_extension_list_free (providers);
5597 
5598 	return items;
5599 }
5600 
5601 typedef struct
5602 {
5603 	NemoMenuItem *item;
5604 	NemoView *view;
5605 	GList *selection;
5606 	GtkAction *action;
5607 } ExtensionActionCallbackData;
5608 
5609 
5610 static void
extension_action_callback_data_free(ExtensionActionCallbackData * data)5611 extension_action_callback_data_free (ExtensionActionCallbackData *data)
5612 {
5613 	g_object_unref (data->item);
5614 	nemo_file_list_free (data->selection);
5615 
5616 	g_free (data);
5617 }
5618 
5619 static gboolean
search_in_menu_items(GList * items,const char * item_name)5620 search_in_menu_items (GList* items, const char *item_name)
5621 {
5622 	GList* list;
5623 
5624 	for (list = items; list != NULL; list = list->next) {
5625 		NemoMenu* menu;
5626 		char *name;
5627 
5628 		g_object_get (list->data, "name", &name, NULL);
5629 		if (strcmp (name, item_name) == 0) {
5630 			g_free (name);
5631 			return TRUE;
5632 		}
5633 		g_free (name);
5634 
5635 		menu = NULL;
5636 		g_object_get (list->data, "menu", &menu, NULL);
5637 		if (menu != NULL) {
5638 			gboolean ret;
5639 			GList* submenus;
5640 
5641 			submenus = nemo_menu_get_items (menu);
5642 			ret = search_in_menu_items (submenus, item_name);
5643 			nemo_menu_item_list_free (submenus);
5644 			g_object_unref (menu);
5645 			if (ret) {
5646 				return TRUE;
5647 			}
5648 		}
5649 	}
5650 	return FALSE;
5651 }
5652 
5653 static void
extension_action_callback(GtkAction * action,gpointer callback_data)5654 extension_action_callback (GtkAction *action,
5655 			   gpointer callback_data)
5656 {
5657 	ExtensionActionCallbackData *data;
5658 	char *item_name;
5659 	gboolean is_valid;
5660 	GList *l;
5661 	GList *items;
5662 
5663 	data = callback_data;
5664 
5665 	/* Make sure the selected menu item is valid for the final sniffed
5666 	 * mime type */
5667 	g_object_get (data->item, "name", &item_name, NULL);
5668 	items = get_all_extension_menu_items (gtk_widget_get_toplevel (GTK_WIDGET (data->view)),
5669 					      data->selection);
5670 
5671 	is_valid = search_in_menu_items (items, item_name);
5672 
5673 	for (l = items; l != NULL; l = l->next) {
5674 		g_object_unref (l->data);
5675 	}
5676 	g_list_free (items);
5677 
5678 	g_free (item_name);
5679 
5680 	if (is_valid) {
5681 		nemo_menu_item_activate (data->item);
5682 	}
5683 }
5684 
5685 static GdkPixbuf *
get_menu_icon_for_file(NemoFile * file,GtkWidget * widget)5686 get_menu_icon_for_file (NemoFile *file,
5687                         GtkWidget *widget)
5688 {
5689 	NemoIconInfo *info;
5690 	GdkPixbuf *pixbuf;
5691 	int size, scale;
5692 
5693 	size = nemo_get_icon_size_for_stock_size (GTK_ICON_SIZE_MENU);
5694     scale = gtk_widget_get_scale_factor (widget);
5695 
5696 	info = nemo_file_get_icon (file, size, 0, scale, 0);
5697 	pixbuf = nemo_icon_info_get_pixbuf_nodefault_at_size (info, size);
5698 	nemo_icon_info_unref (info);
5699 
5700 	return pixbuf;
5701 }
5702 
5703 static GtkAction *
add_extension_action_for_files(NemoView * view,NemoMenuItem * item,GList * files)5704 add_extension_action_for_files (NemoView *view,
5705 				NemoMenuItem *item,
5706 				GList *files)
5707 {
5708     GtkAction *ret = NULL;
5709 	char *name, *label, *tip, *icon;
5710 	gboolean sensitive, priority;
5711     gboolean separator;
5712 	GtkAction *action;
5713     GtkWidget *widget_a, *widget_b;
5714 	ExtensionActionCallbackData *data;
5715 
5716 	g_object_get (G_OBJECT (item),
5717 		      "name", &name, "label", &label,
5718 		      "tip", &tip, "icon", &icon,
5719 		      "sensitive", &sensitive,
5720 		      "priority", &priority,
5721               "widget-a", &widget_a,
5722               "widget-b", &widget_b,
5723               "separator", &separator,
5724 		      NULL);
5725 
5726     if (widget_a == NULL && !separator) {
5727         action = gtk_action_new (name,
5728                                  label,
5729                                  tip,
5730                                  NULL);
5731         if (icon != NULL) {
5732             GIcon *gicon;
5733 
5734             if (g_path_is_absolute (icon)) {
5735                 GFile *file;
5736 
5737                 file = g_file_new_for_path (icon);
5738                 gicon = g_file_icon_new (file);
5739 
5740                 g_object_unref (file);
5741             } else if (icon) {
5742                 gicon = g_themed_icon_new (icon);
5743             } else {
5744                 gicon = NULL;
5745             }
5746 
5747             gtk_action_set_gicon (action, gicon);
5748 
5749             g_clear_object (&gicon);
5750         }
5751     } else if (separator) {
5752         action = nemo_separator_action_new (name);
5753     } else {
5754         action = nemo_widget_action_new (name, widget_a, widget_b);
5755     }
5756 
5757 	gtk_action_set_sensitive (action, sensitive);
5758 	g_object_set (action, "is-important", priority, NULL);
5759 
5760 	data = g_new0 (ExtensionActionCallbackData, 1);
5761 	data->item = g_object_ref (item);
5762 	data->view = view;
5763 	data->selection = nemo_file_list_copy (files);
5764 	data->action = action;
5765 
5766 	g_signal_connect_data (action, "activate",
5767 			       G_CALLBACK (extension_action_callback),
5768 			       data,
5769 			       (GClosureNotify)extension_action_callback_data_free, 0);
5770 
5771     if (gtk_action_group_get_action (view->details->extensions_menu_action_group, gtk_action_get_name (GTK_ACTION (action))) == NULL) {
5772         gtk_action_group_add_action (view->details->extensions_menu_action_group,
5773                                      GTK_ACTION (action));
5774         ret = action;
5775     }
5776 
5777 	g_object_unref (action);
5778 
5779 	g_free (name);
5780 	g_free (label);
5781 	g_free (tip);
5782 	g_free (icon);
5783 
5784 	return ret;
5785 }
5786 
5787 static void
add_extension_menu_items(NemoView * view,GList * files,GList * menu_items,const char * subdirectory)5788 add_extension_menu_items (NemoView *view,
5789 			  GList *files,
5790 			  GList *menu_items,
5791 			  const char *subdirectory)
5792 {
5793 	GtkUIManager *ui_manager;
5794 	GList *l;
5795 
5796 	ui_manager = nemo_window_get_ui_manager (view->details->window);
5797 
5798 	for (l = menu_items; l; l = l->next) {
5799 		NemoMenuItem *item;
5800 		NemoMenu *menu;
5801 		GtkAction *action = NULL;
5802 		char *path;
5803 
5804 		item = NEMO_MENU_ITEM (l->data);
5805 
5806 		g_object_get (item, "menu", &menu, NULL);
5807 
5808 		action = add_extension_action_for_files (view, item, files);
5809 
5810         if (action) {
5811             GtkUIManagerItemType item_type;
5812 
5813             if (G_OBJECT_TYPE (action) == NEMO_TYPE_SEPARATOR_ACTION)
5814                 item_type = GTK_UI_MANAGER_SEPARATOR;
5815             else {
5816                 item_type = (menu != NULL) ? GTK_UI_MANAGER_MENU : GTK_UI_MANAGER_MENUITEM;
5817             }
5818     		path = g_build_path ("/", NEMO_VIEW_POPUP_PATH_EXTENSION_ACTIONS, subdirectory, NULL);
5819     		gtk_ui_manager_add_ui (ui_manager,
5820     				       view->details->extensions_menu_merge_id,
5821     				       path,
5822     				       gtk_action_get_name (action),
5823     				       gtk_action_get_name (action),
5824     				       item_type,
5825     				       FALSE);
5826     		g_free (path);
5827 
5828     		path = g_build_path ("/", NEMO_VIEW_MENU_PATH_EXTENSION_ACTIONS_PLACEHOLDER, subdirectory, NULL);
5829     		gtk_ui_manager_add_ui (ui_manager,
5830     				       view->details->extensions_menu_merge_id,
5831     				       path,
5832     				       gtk_action_get_name (action),
5833     				       gtk_action_get_name (action),
5834                            item_type,
5835     				       FALSE);
5836     		g_free (path);
5837 
5838     		/* recursively fill the menu */
5839     		if (menu != NULL) {
5840     			char *subdir;
5841     			GList *children;
5842 
5843     			children = nemo_menu_get_items (menu);
5844 
5845     			subdir = g_build_path ("/", subdirectory, gtk_action_get_name (action), NULL);
5846     			add_extension_menu_items (view,
5847     						  files,
5848     						  children,
5849     						  subdir);
5850 
5851     			nemo_menu_item_list_free (children);
5852     			g_free (subdir);
5853     		}
5854         }
5855 	}
5856 }
5857 
5858 static void
reset_extension_actions_menu(NemoView * view,GList * selection)5859 reset_extension_actions_menu (NemoView *view, GList *selection)
5860 {
5861 	GList *items;
5862 	GtkUIManager *ui_manager;
5863 
5864 	/* Clear any previous inserted items in the extension actions placeholder */
5865 	ui_manager = nemo_window_get_ui_manager (view->details->window);
5866 
5867 	nemo_ui_unmerge_ui (ui_manager,
5868 				&view->details->extensions_menu_merge_id,
5869 				&view->details->extensions_menu_action_group);
5870 
5871 	nemo_ui_prepare_merge_ui (ui_manager,
5872 				      "DirExtensionsMenuGroup",
5873 				      &view->details->extensions_menu_merge_id,
5874 				      &view->details->extensions_menu_action_group);
5875 
5876 	items = get_all_extension_menu_items (gtk_widget_get_toplevel (GTK_WIDGET (view)),
5877 					      selection);
5878 	if (items != NULL) {
5879 		add_extension_menu_items (view, selection, items, "");
5880 
5881 		g_list_foreach (items, (GFunc) g_object_unref, NULL);
5882 		g_list_free (items);
5883 	}
5884 }
5885 
5886 static char *
change_to_view_directory(NemoView * view)5887 change_to_view_directory (NemoView *view)
5888 {
5889 	char *path;
5890 	char *old_path;
5891 
5892 	old_path = g_get_current_dir ();
5893 
5894 	path = get_view_directory (view);
5895 
5896 	/* FIXME: What to do about non-local directories? */
5897 	if (path != NULL) {
5898 		g_chdir (path);
5899 	}
5900 
5901 	g_free (path);
5902 
5903 	return old_path;
5904 }
5905 
5906 static char **
get_file_names_as_parameter_array(GList * selection,NemoDirectory * model)5907 get_file_names_as_parameter_array (GList *selection,
5908 				   NemoDirectory *model)
5909 {
5910 	NemoFile *file;
5911 	char **parameters;
5912 	GList *node;
5913 	GFile *file_location;
5914 	GFile *model_location;
5915 	int i;
5916 
5917 	if (model == NULL) {
5918 		return NULL;
5919 	}
5920 
5921 	parameters = g_new (char *, g_list_length (selection) + 1);
5922 
5923 	model_location = nemo_directory_get_location (model);
5924 
5925 	for (node = selection, i = 0; node != NULL; node = node->next, i++) {
5926 		file = NEMO_FILE (node->data);
5927 
5928 		if (!nemo_file_is_local (file)) {
5929 			parameters[i] = NULL;
5930 			g_strfreev (parameters);
5931 			return NULL;
5932 		}
5933 
5934 		file_location = nemo_file_get_location (NEMO_FILE (node->data));
5935 		parameters[i] = g_file_get_relative_path (model_location, file_location);
5936 		if (parameters[i] == NULL) {
5937 			parameters[i] = g_file_get_path (file_location);
5938 		}
5939 		g_object_unref (file_location);
5940 	}
5941 
5942 	g_object_unref (model_location);
5943 
5944 	parameters[i] = NULL;
5945 	return parameters;
5946 }
5947 
5948 static char *
get_file_paths_or_uris_as_newline_delimited_string(GList * selection,gboolean get_paths)5949 get_file_paths_or_uris_as_newline_delimited_string (GList *selection, gboolean get_paths)
5950 {
5951 	char *path;
5952 	char *uri;
5953 	char *result;
5954 	NemoDesktopLink *link;
5955 	GString *expanding_string;
5956 	GList *node;
5957 	GFile *location;
5958 
5959 	expanding_string = g_string_new ("");
5960 	for (node = selection; node != NULL; node = node->next) {
5961 		uri = NULL;
5962 		if (NEMO_IS_DESKTOP_ICON_FILE (node->data)) {
5963 			link = nemo_desktop_icon_file_get_link (NEMO_DESKTOP_ICON_FILE (node->data));
5964 			if (link != NULL) {
5965 				location = nemo_desktop_link_get_activation_location (link);
5966 				uri = g_file_get_uri (location);
5967 				g_object_unref (location);
5968 				g_object_unref (G_OBJECT (link));
5969 			}
5970 		} else {
5971 			uri = nemo_file_get_uri (NEMO_FILE (node->data));
5972 		}
5973 		if (uri == NULL) {
5974 			continue;
5975 		}
5976 
5977 		if (get_paths) {
5978 			path = g_filename_from_uri (uri, NULL, NULL);
5979 			if (path != NULL) {
5980 				g_string_append (expanding_string, path);
5981 				g_free (path);
5982 				g_string_append (expanding_string, "\n");
5983 			}
5984 		} else {
5985 			g_string_append (expanding_string, uri);
5986 			g_string_append (expanding_string, "\n");
5987 		}
5988 		g_free (uri);
5989 	}
5990 
5991 	result = expanding_string->str;
5992 	g_string_free (expanding_string, FALSE);
5993 
5994 	return result;
5995 }
5996 
5997 static char *
get_file_paths_as_newline_delimited_string(GList * selection)5998 get_file_paths_as_newline_delimited_string (GList *selection)
5999 {
6000 	return get_file_paths_or_uris_as_newline_delimited_string (selection, TRUE);
6001 }
6002 
6003 static char *
get_file_uris_as_newline_delimited_string(GList * selection)6004 get_file_uris_as_newline_delimited_string (GList *selection)
6005 {
6006 	return get_file_paths_or_uris_as_newline_delimited_string (selection, FALSE);
6007 }
6008 
6009 /* returns newly allocated strings for setting the environment variables */
6010 static void
get_strings_for_environment_variables(NemoView * view,GList * selected_files,char ** file_paths,char ** uris,char ** uri)6011 get_strings_for_environment_variables (NemoView *view, GList *selected_files,
6012 				       char **file_paths, char **uris, char **uri)
6013 {
6014 	char *directory_uri;
6015 
6016 	/* We need to check that the directory uri starts with "file:" since
6017 	 * nemo_directory_is_local returns FALSE for nfs.
6018 	 */
6019 	directory_uri = nemo_directory_get_uri (view->details->model);
6020 	if (g_str_has_prefix (directory_uri, "file:") ||
6021 	    eel_uri_is_desktop (directory_uri) ||
6022 	    eel_uri_is_trash (directory_uri)) {
6023 		*file_paths = get_file_paths_as_newline_delimited_string (selected_files);
6024 	} else {
6025 		*file_paths = g_strdup ("");
6026 	}
6027 	g_free (directory_uri);
6028 
6029 	*uris = get_file_uris_as_newline_delimited_string (selected_files);
6030 
6031 	*uri = nemo_directory_get_uri (view->details->model);
6032 	if (eel_uri_is_desktop (*uri)) {
6033 		g_free (*uri);
6034 		*uri = nemo_get_desktop_directory_uri ();
6035 	}
6036 }
6037 
6038 static NemoView *
get_directory_view_of_extra_pane(NemoView * view)6039 get_directory_view_of_extra_pane (NemoView *view)
6040 {
6041 	NemoWindowSlot *slot;
6042 	NemoView *next_view;
6043 
6044 	slot = nemo_window_get_extra_slot (nemo_view_get_nemo_window (view));
6045 	if (slot != NULL) {
6046 		next_view = nemo_window_slot_get_current_view (slot);
6047 
6048 		if (NEMO_IS_VIEW (next_view)) {
6049 			return NEMO_VIEW (next_view);
6050 		}
6051 	}
6052 	return NULL;
6053 }
6054 
6055 /*
6056  * Set up some environment variables that scripts can use
6057  * to take advantage of the current Nemo state.
6058  */
6059 static void
set_script_environment_variables(NemoView * view,GList * selected_files)6060 set_script_environment_variables (NemoView *view, GList *selected_files)
6061 {
6062 	char *file_paths;
6063 	char *uris;
6064 	char *uri;
6065 	char *geometry_string;
6066 	NemoView *next_view;
6067 
6068 	get_strings_for_environment_variables (view, selected_files,
6069 					       &file_paths, &uris, &uri);
6070 
6071 	g_setenv ("NEMO_SCRIPT_SELECTED_FILE_PATHS", file_paths, TRUE);
6072 	g_free (file_paths);
6073 
6074 	g_setenv ("NEMO_SCRIPT_SELECTED_URIS", uris, TRUE);
6075 	g_free (uris);
6076 
6077 	g_setenv ("NEMO_SCRIPT_CURRENT_URI", uri, TRUE);
6078 	g_free (uri);
6079 
6080 	geometry_string = eel_gtk_window_get_geometry_string
6081 		(GTK_WINDOW (nemo_view_get_containing_window (view)));
6082 	g_setenv ("NEMO_SCRIPT_WINDOW_GEOMETRY", geometry_string, TRUE);
6083 	g_free (geometry_string);
6084 
6085 	/* next pane */
6086 	next_view = get_directory_view_of_extra_pane (view);
6087 	if (next_view) {
6088 		GList *next_pane_selected_files;
6089 		next_pane_selected_files = nemo_view_get_selection (next_view);
6090 
6091 		get_strings_for_environment_variables (next_view, next_pane_selected_files,
6092 						       &file_paths, &uris, &uri);
6093 		nemo_file_list_free (next_pane_selected_files);
6094 	} else {
6095 		file_paths = g_strdup("");
6096 		uris = g_strdup("");
6097 		uri = g_strdup("");
6098 	}
6099 
6100 	g_setenv ("NEMO_SCRIPT_NEXT_PANE_SELECTED_FILE_PATHS", file_paths, TRUE);
6101 	g_free (file_paths);
6102 
6103 	g_setenv ("NEMO_SCRIPT_NEXT_PANE_SELECTED_URIS", uris, TRUE);
6104 	g_free (uris);
6105 
6106 	g_setenv ("NEMO_SCRIPT_NEXT_PANE_CURRENT_URI", uri, TRUE);
6107 	g_free (uri);
6108 }
6109 
6110 /* Unset all the special script environment variables. */
6111 static void
unset_script_environment_variables(void)6112 unset_script_environment_variables (void)
6113 {
6114 	g_unsetenv ("NEMO_SCRIPT_SELECTED_FILE_PATHS");
6115 	g_unsetenv ("NEMO_SCRIPT_SELECTED_URIS");
6116 	g_unsetenv ("NEMO_SCRIPT_CURRENT_URI");
6117 	g_unsetenv ("NEMO_SCRIPT_WINDOW_GEOMETRY");
6118 	g_unsetenv ("NEMO_SCRIPT_NEXT_PANE_SELECTED_FILE_PATHS");
6119 	g_unsetenv ("NEMO_SCRIPT_NEXT_PANE_SELECTED_URIS");
6120 	g_unsetenv ("NEMO_SCRIPT_NEXT_PANE_CURRENT_URI");
6121 }
6122 
6123 static void
run_script_callback(GtkAction * action,gpointer callback_data)6124 run_script_callback (GtkAction *action, gpointer callback_data)
6125 {
6126 	ScriptLaunchParameters *launch_parameters;
6127 	GdkScreen *screen;
6128 	GList *selected_files;
6129 	char *file_uri;
6130 	char *local_file_path;
6131 	char *quoted_path;
6132 	char *old_working_dir;
6133 	char **parameters;
6134 
6135 	launch_parameters = (ScriptLaunchParameters *) callback_data;
6136 
6137 	file_uri = nemo_file_get_uri (launch_parameters->file);
6138 	local_file_path = g_filename_from_uri (file_uri, NULL, NULL);
6139 	g_assert (local_file_path != NULL);
6140 	g_free (file_uri);
6141 
6142 	quoted_path = g_shell_quote (local_file_path);
6143 	g_free (local_file_path);
6144 
6145 	old_working_dir = change_to_view_directory (launch_parameters->directory_view);
6146 
6147 	selected_files = nemo_view_get_selection (launch_parameters->directory_view);
6148 	set_script_environment_variables (launch_parameters->directory_view, selected_files);
6149 
6150 	parameters = get_file_names_as_parameter_array (selected_files,
6151 						        launch_parameters->directory_view->details->model);
6152 
6153 	screen = gtk_widget_get_screen (GTK_WIDGET (launch_parameters->directory_view));
6154 
6155 	DEBUG ("run_script_callback, script_path=\"%s\" (omitting script parameters)",
6156 	       local_file_path);
6157 
6158 	nemo_launch_application_from_command_array (screen, quoted_path, FALSE,
6159 							(const char * const *) parameters);
6160 	g_strfreev (parameters);
6161 
6162 	nemo_file_list_free (selected_files);
6163 	unset_script_environment_variables ();
6164 	g_chdir (old_working_dir);
6165 	g_free (old_working_dir);
6166 	g_free (quoted_path);
6167 }
6168 
6169 static void
add_script_to_scripts_menus(NemoView * directory_view,NemoFile * file,const char * menu_path,const char * popup_path,const char * popup_bg_path)6170 add_script_to_scripts_menus (NemoView *directory_view,
6171 			     NemoFile *file,
6172 			     const char *menu_path,
6173 			     const char *popup_path,
6174 			     const char *popup_bg_path)
6175 {
6176 	ScriptLaunchParameters *launch_parameters;
6177 	char *tip;
6178 	char *name;
6179 	char *uri;
6180 	char *action_name;
6181 	char *escaped_label;
6182 	GdkPixbuf *pixbuf;
6183 	GtkUIManager *ui_manager;
6184 	GtkAction *action;
6185 
6186 	name = nemo_file_get_display_name (file);
6187 	uri = nemo_file_get_uri (file);
6188 	tip = g_strdup_printf (_("Run \"%s\" on any selected items"), name);
6189 
6190 	launch_parameters = script_launch_parameters_new (file, directory_view);
6191 
6192 	action_name = escape_action_name (uri, "script_");
6193 	escaped_label = eel_str_double_underscores (name);
6194 
6195 	action = gtk_action_new (action_name,
6196 				 escaped_label,
6197 				 tip,
6198 				 NULL);
6199 
6200 	pixbuf = get_menu_icon_for_file (file, GTK_WIDGET (directory_view));
6201 	if (pixbuf != NULL) {
6202 		gtk_action_set_gicon (action, G_ICON (pixbuf));
6203 		g_object_unref (pixbuf);
6204 	}
6205 
6206 	g_signal_connect_data (action, "activate",
6207 			       G_CALLBACK (run_script_callback),
6208 			       launch_parameters,
6209 			       (GClosureNotify)script_launch_parameters_free, 0);
6210 
6211 	gtk_action_group_add_action_with_accel (directory_view->details->scripts_action_group,
6212 						action, NULL);
6213 	g_object_unref (action);
6214 
6215 	ui_manager = nemo_window_get_ui_manager (directory_view->details->window);
6216 
6217 	gtk_ui_manager_add_ui (ui_manager,
6218 			       directory_view->details->scripts_merge_id,
6219 			       menu_path,
6220 			       action_name,
6221 			       action_name,
6222 			       GTK_UI_MANAGER_MENUITEM,
6223 			       FALSE);
6224 	gtk_ui_manager_add_ui (ui_manager,
6225 			       directory_view->details->scripts_merge_id,
6226 			       popup_path,
6227 			       action_name,
6228 			       action_name,
6229 			       GTK_UI_MANAGER_MENUITEM,
6230 			       FALSE);
6231 	gtk_ui_manager_add_ui (ui_manager,
6232 			       directory_view->details->scripts_merge_id,
6233 			       popup_bg_path,
6234 			       action_name,
6235 			       action_name,
6236 			       GTK_UI_MANAGER_MENUITEM,
6237 			       FALSE);
6238 
6239 	menu_item_show_image (ui_manager, menu_path, action_name, FALSE);
6240 	menu_item_show_image (ui_manager, popup_path, action_name, FALSE);
6241 	menu_item_show_image (ui_manager, popup_bg_path, action_name, FALSE);
6242 
6243 	g_free (name);
6244 	g_free (uri);
6245 	g_free (tip);
6246 	g_free (action_name);
6247 	g_free (escaped_label);
6248 }
6249 
6250 static void
add_submenu_to_directory_menus(NemoView * directory_view,GtkActionGroup * action_group,guint merge_id,NemoFile * file,const char * menu_path,const char * popup_path,const char * popup_bg_path)6251 add_submenu_to_directory_menus (NemoView *directory_view,
6252 				GtkActionGroup *action_group,
6253 				guint merge_id,
6254 				NemoFile *file,
6255 				const char *menu_path,
6256 				const char *popup_path,
6257 				const char *popup_bg_path)
6258 {
6259 	char *name;
6260 	GdkPixbuf *pixbuf;
6261 	char *uri;
6262 	GtkUIManager *ui_manager;
6263 
6264 	ui_manager = nemo_window_get_ui_manager (directory_view->details->window);
6265 	uri = nemo_file_get_uri (file);
6266 	name = nemo_file_get_display_name (file);
6267 	pixbuf = get_menu_icon_for_file (file, GTK_WIDGET (directory_view));
6268 	add_submenu (ui_manager, action_group, merge_id, menu_path, uri, name, pixbuf, TRUE);
6269 	add_submenu (ui_manager, action_group, merge_id, popup_path, uri, name, pixbuf, FALSE);
6270 	add_submenu (ui_manager, action_group, merge_id, popup_bg_path, uri, name, pixbuf, FALSE);
6271 	if (pixbuf) {
6272 		g_object_unref (pixbuf);
6273 	}
6274 	g_free (name);
6275 	g_free (uri);
6276 }
6277 
6278 static gboolean
directory_belongs_in_scripts_menu(const char * uri)6279 directory_belongs_in_scripts_menu (const char *uri)
6280 {
6281 	int num_levels;
6282 	int i;
6283 
6284 	if (!g_str_has_prefix (uri, scripts_directory_uri)) {
6285 		return FALSE;
6286 	}
6287 
6288 	num_levels = 0;
6289 	for (i = scripts_directory_uri_length; uri[i] != '\0'; i++) {
6290 		if (uri[i] == '/') {
6291 			num_levels++;
6292 		}
6293 	}
6294 
6295 	if (num_levels > MAX_MENU_LEVELS) {
6296 		return FALSE;
6297 	}
6298 
6299 	return TRUE;
6300 }
6301 
6302 static gboolean
update_directory_in_scripts_menu(NemoView * view,NemoDirectory * directory)6303 update_directory_in_scripts_menu (NemoView *view, NemoDirectory *directory)
6304 {
6305 	char *menu_path, *popup_path, *popup_bg_path;
6306 	GList *file_list, *filtered, *node;
6307 	gboolean any_scripts;
6308 	NemoFile *file;
6309 	NemoDirectory *dir;
6310 	char *uri;
6311 	char *escaped_path;
6312 
6313 	uri = nemo_directory_get_uri (directory);
6314 	escaped_path = escape_action_path (uri + scripts_directory_uri_length);
6315 	g_free (uri);
6316 	menu_path = g_strconcat (NEMO_VIEW_MENU_PATH_SCRIPTS_PLACEHOLDER,
6317 				 escaped_path,
6318 				 NULL);
6319 	popup_path = g_strconcat (NEMO_VIEW_POPUP_PATH_SCRIPTS_PLACEHOLDER,
6320 				  escaped_path,
6321 				  NULL);
6322 	popup_bg_path = g_strconcat (NEMO_VIEW_POPUP_PATH_BACKGROUND_SCRIPTS_PLACEHOLDER,
6323 				     escaped_path,
6324 				     NULL);
6325 	g_free (escaped_path);
6326 
6327 	file_list = nemo_directory_get_file_list (directory);
6328 	filtered = nemo_file_list_filter_hidden (file_list, FALSE);
6329 	nemo_file_list_free (file_list);
6330 
6331 	file_list = nemo_file_list_sort_by_display_name (filtered);
6332 
6333 	any_scripts = FALSE;
6334 	for (node = file_list; node != NULL; node = node->next) {
6335 		file = node->data;
6336 
6337 		if (nemo_file_is_launchable (file) &&
6338             nemo_global_preferences_should_load_plugin (nemo_file_peek_name (file), NEMO_PLUGIN_PREFERENCES_DISABLED_SCRIPTS)) {
6339 			add_script_to_scripts_menus (view, file, menu_path, popup_path, popup_bg_path);
6340 			any_scripts = TRUE;
6341 		} else if (nemo_file_is_directory (file)) {
6342 			uri = nemo_file_get_uri (file);
6343 			if (directory_belongs_in_scripts_menu (uri)) {
6344 				dir = nemo_directory_get_by_uri (uri);
6345 				add_directory_to_scripts_directory_list (view, dir);
6346 				nemo_directory_unref (dir);
6347 
6348 				add_submenu_to_directory_menus (view,
6349 								view->details->scripts_action_group,
6350 								view->details->scripts_merge_id,
6351 								file, menu_path, popup_path, popup_bg_path);
6352 
6353 				any_scripts = TRUE;
6354 			}
6355 			g_free (uri);
6356 		}
6357 	}
6358 
6359 	nemo_file_list_free (file_list);
6360 
6361 	g_free (popup_path);
6362 	g_free (popup_bg_path);
6363 	g_free (menu_path);
6364 
6365 	return any_scripts;
6366 }
6367 
6368 static void
update_scripts_menu(NemoView * view)6369 update_scripts_menu (NemoView *view)
6370 {
6371 	gboolean any_scripts;
6372 	GList *sorted_copy, *node;
6373 	NemoDirectory *directory;
6374 	char *uri;
6375 	GtkUIManager *ui_manager;
6376 	GtkAction *action;
6377 
6378 	/* There is a race condition here.  If we don't mark the scripts menu as
6379 	   valid before we begin our task then we can lose script menu updates that
6380 	   occur before we finish. */
6381 	view->details->scripts_invalid = FALSE;
6382 
6383 	ui_manager = nemo_window_get_ui_manager (view->details->window);
6384 	nemo_ui_unmerge_ui (ui_manager,
6385 				&view->details->scripts_merge_id,
6386 				&view->details->scripts_action_group);
6387 
6388 	nemo_ui_prepare_merge_ui (ui_manager,
6389 				      "ScriptsGroup",
6390 				      &view->details->scripts_merge_id,
6391 				      &view->details->scripts_action_group);
6392 
6393 	/* As we walk through the directories, remove any that no longer belong. */
6394 	any_scripts = FALSE;
6395 	sorted_copy = nemo_directory_list_sort_by_uri
6396 		(nemo_directory_list_copy (view->details->scripts_directory_list));
6397 	for (node = sorted_copy; node != NULL; node = node->next) {
6398 		directory = node->data;
6399 
6400 		uri = nemo_directory_get_uri (directory);
6401 		if (!directory_belongs_in_scripts_menu (uri)) {
6402 			remove_directory_from_scripts_directory_list (view, directory);
6403 		} else if (update_directory_in_scripts_menu (view, directory)) {
6404 			any_scripts = TRUE;
6405 		}
6406 		g_free (uri);
6407 	}
6408 	nemo_directory_list_free (sorted_copy);
6409 
6410 	action = gtk_action_group_get_action (view->details->dir_action_group, NEMO_ACTION_SCRIPTS);
6411 	gtk_action_set_visible (action, any_scripts);
6412 }
6413 
6414 static void
run_action_callback(NemoAction * action,gpointer callback_data)6415 run_action_callback (NemoAction *action, gpointer callback_data)
6416 {
6417 
6418     NemoView *view = NEMO_VIEW (callback_data);
6419     GList *selected_files;
6420 
6421     selected_files = nemo_view_get_selection (view);
6422     NemoFile *parent = nemo_view_get_directory_as_file (view);
6423 
6424     nemo_action_activate (action, selected_files, parent);
6425 
6426     nemo_file_list_free (selected_files);
6427 }
6428 
6429 typedef struct {
6430     NemoView *view;
6431     GList    *selection;
6432 } ActionVisibilityData;
6433 
6434 static void
determine_visibility(gpointer data,gpointer callback_data)6435 determine_visibility (gpointer data, gpointer callback_data)
6436 {
6437     NemoAction *action = NEMO_ACTION (data);
6438     ActionVisibilityData *av_data = (ActionVisibilityData *) callback_data;
6439     GList *selection;
6440     NemoView *view;
6441 
6442     view = av_data->view;
6443     selection = av_data->selection;
6444 
6445     NemoFile *parent = nemo_view_get_directory_as_file (view);
6446 
6447     if (nemo_action_get_visibility (action, selection, parent, FALSE)) {
6448         gchar *label, *tt;
6449 
6450         label = nemo_action_get_label (action, selection, parent);
6451         tt = nemo_action_get_tt (action, selection, parent);
6452 
6453         gtk_action_set_label (GTK_ACTION (action), label);
6454         gtk_action_set_tooltip (GTK_ACTION (action), tt);
6455 
6456         g_free (label);
6457         g_free (tt);
6458 
6459         gtk_action_set_visible (GTK_ACTION (action), TRUE);
6460     } else {
6461         gtk_action_set_visible (GTK_ACTION (action), FALSE);
6462     }
6463 }
6464 
6465 static void
update_actions_visibility(NemoView * view,GList * selection)6466 update_actions_visibility (NemoView *view, GList *selection)
6467 {
6468     GList *actions = gtk_action_group_list_actions (view->details->actions_action_group);
6469     ActionVisibilityData data;
6470 
6471     data.view = view;
6472     data.selection = selection;
6473 
6474     g_list_foreach (actions, determine_visibility, &data);
6475 
6476     g_list_free (actions);
6477 }
6478 
6479 static void
add_action_to_action_menus(NemoView * directory_view,NemoAction * action,const char * menu_path,const char * popup_path,const char * popup_bg_path)6480 add_action_to_action_menus (NemoView *directory_view,
6481                             NemoAction *action,
6482                           const char *menu_path,
6483                           const char *popup_path,
6484                           const char *popup_bg_path)
6485 {
6486     GtkUIManager *ui_manager;
6487 
6488     const gchar *action_name = gtk_action_get_name (GTK_ACTION (action));
6489 
6490     gtk_action_group_add_action (directory_view->details->actions_action_group,
6491                                  GTK_ACTION (action));
6492 
6493     gtk_action_set_visible (GTK_ACTION (action), FALSE);
6494 
6495     g_signal_handlers_disconnect_by_func (action,
6496                                           run_action_callback,
6497                                           directory_view);
6498 
6499     g_signal_connect (action, "activate",
6500                    G_CALLBACK (run_action_callback),
6501                    directory_view);
6502 
6503     ui_manager = nemo_window_get_ui_manager (directory_view->details->window);
6504 
6505     gtk_ui_manager_add_ui (ui_manager,
6506                    directory_view->details->actions_merge_id,
6507                    menu_path,
6508                    action_name,
6509                    action_name,
6510                    GTK_UI_MANAGER_MENUITEM,
6511                    FALSE);
6512     gtk_ui_manager_add_ui (ui_manager,
6513                    directory_view->details->actions_merge_id,
6514                    popup_path,
6515                    action_name,
6516                    action_name,
6517                    GTK_UI_MANAGER_MENUITEM,
6518                    FALSE);
6519     gtk_ui_manager_add_ui (ui_manager,
6520                    directory_view->details->actions_merge_id,
6521                    popup_bg_path,
6522                    action_name,
6523                    action_name,
6524                    GTK_UI_MANAGER_MENUITEM,
6525                    FALSE);
6526 }
6527 
6528 static void
update_actions(NemoView * view)6529 update_actions (NemoView *view)
6530 {
6531     NemoAction *action;
6532     GList *action_list, *node;
6533 
6534     action_list = nemo_action_manager_list_actions (view->details->action_manager);
6535 
6536     for (node = action_list; node != NULL; node = node->next) {
6537         action = node->data;
6538         add_action_to_action_menus (view, action, NEMO_VIEW_MENU_PATH_ACTIONS_PLACEHOLDER,
6539                                                   NEMO_VIEW_POPUP_PATH_ACTIONS_PLACEHOLDER,
6540                                                   NEMO_VIEW_POPUP_PATH_BACKGROUND_ACTIONS_PLACEHOLDER);
6541     }
6542 }
6543 
6544 static void
update_actions_menu(NemoView * view)6545 update_actions_menu (NemoView *view)
6546 {
6547     GtkUIManager *ui_manager;
6548 
6549     view->details->actions_invalid = FALSE;
6550 
6551     ui_manager = nemo_window_get_ui_manager (view->details->window);
6552     nemo_ui_unmerge_ui (ui_manager,
6553                 &view->details->actions_merge_id,
6554                 &view->details->actions_action_group);
6555 
6556     nemo_ui_prepare_merge_ui (ui_manager,
6557                       "ActionsGroup",
6558                       &view->details->actions_merge_id,
6559                       &view->details->actions_action_group);
6560 
6561     update_actions (view);
6562 }
6563 
6564 static void
create_template_callback(GtkAction * action,gpointer callback_data)6565 create_template_callback (GtkAction *action, gpointer callback_data)
6566 {
6567 	CreateTemplateParameters *parameters;
6568 
6569 	parameters = callback_data;
6570 
6571 	nemo_view_new_file (parameters->directory_view, NULL, parameters->file);
6572 }
6573 
6574 static void
add_template_to_templates_menus(NemoView * directory_view,NemoFile * file,const char * menu_path,const char * popup_bg_path)6575 add_template_to_templates_menus (NemoView *directory_view,
6576 				 NemoFile *file,
6577 				 const char *menu_path,
6578 				 const char *popup_bg_path)
6579 {
6580 	char *tmp, *tip, *uri, *name;
6581 	char *escaped_label;
6582 	GdkPixbuf *pixbuf;
6583 	char *action_name;
6584 	CreateTemplateParameters *parameters;
6585 	GtkUIManager *ui_manager;
6586 	GtkAction *action;
6587 
6588 	tmp = nemo_file_get_display_name (file);
6589 	name = eel_filename_strip_extension (tmp);
6590 	g_free (tmp);
6591 
6592 	uri = nemo_file_get_uri (file);
6593 	tip = g_strdup_printf (_("Create a new document from template \"%s\""), name);
6594 
6595 	action_name = escape_action_name (uri, "template_");
6596 	escaped_label = eel_str_double_underscores (name);
6597 
6598 	parameters = create_template_parameters_new (file, directory_view);
6599 
6600 	action = gtk_action_new (action_name,
6601 				 escaped_label,
6602 				 tip,
6603 				 NULL);
6604 
6605 	pixbuf = get_menu_icon_for_file (file, GTK_WIDGET (directory_view));
6606 	if (pixbuf != NULL) {
6607 		gtk_action_set_gicon (action, G_ICON (pixbuf));
6608 		g_object_unref (pixbuf);
6609 	}
6610 
6611 	g_signal_connect_data (action, "activate",
6612 			       G_CALLBACK (create_template_callback),
6613 			       parameters,
6614 			       (GClosureNotify)create_templates_parameters_free, 0);
6615 
6616 	gtk_action_group_add_action (directory_view->details->templates_action_group,
6617 				     action);
6618 	g_object_unref (action);
6619 
6620 	ui_manager = nemo_window_get_ui_manager (directory_view->details->window);
6621 
6622 	gtk_ui_manager_add_ui (ui_manager,
6623 			       directory_view->details->templates_merge_id,
6624 			       menu_path,
6625 			       action_name,
6626 			       action_name,
6627 			       GTK_UI_MANAGER_MENUITEM,
6628 			       FALSE);
6629 
6630 	gtk_ui_manager_add_ui (ui_manager,
6631 			       directory_view->details->templates_merge_id,
6632 			       popup_bg_path,
6633 			       action_name,
6634 			       action_name,
6635 			       GTK_UI_MANAGER_MENUITEM,
6636 			       FALSE);
6637 
6638 	menu_item_show_image (ui_manager, menu_path, action_name, TRUE);
6639 	menu_item_show_image (ui_manager, popup_bg_path, action_name, TRUE);
6640 
6641 	g_free (escaped_label);
6642 	g_free (name);
6643 	g_free (tip);
6644 	g_free (uri);
6645 	g_free (action_name);
6646 }
6647 
6648 static void
update_templates_directory(NemoView * view)6649 update_templates_directory (NemoView *view)
6650 {
6651 	NemoDirectory *templates_directory;
6652 	GList *node, *next;
6653 	char *templates_uri;
6654 
6655 	for (node = view->details->templates_directory_list; node != NULL; node = next) {
6656 		next = node->next;
6657 		remove_directory_from_templates_directory_list (view, node->data);
6658 	}
6659 
6660 	if (nemo_should_use_templates_directory ()) {
6661 		templates_uri = nemo_get_templates_directory_uri ();
6662 		templates_directory = nemo_directory_get_by_uri (templates_uri);
6663 		g_free (templates_uri);
6664 		add_directory_to_templates_directory_list (view, templates_directory);
6665 		nemo_directory_unref (templates_directory);
6666 	}
6667 }
6668 
6669 static void
user_dirs_changed(NemoView * view)6670 user_dirs_changed (NemoView *view)
6671 {
6672 	update_templates_directory (view);
6673 	view->details->templates_invalid = TRUE;
6674 	schedule_update_menus (view);
6675 }
6676 
6677 static gboolean
directory_belongs_in_templates_menu(const char * templates_directory_uri,const char * uri)6678 directory_belongs_in_templates_menu (const char *templates_directory_uri,
6679 				     const char *uri)
6680 {
6681 	int num_levels;
6682 	int i;
6683 
6684 	if (templates_directory_uri == NULL) {
6685 		return FALSE;
6686 	}
6687 
6688 	if (!g_str_has_prefix (uri, templates_directory_uri)) {
6689 		return FALSE;
6690 	}
6691 
6692 	num_levels = 0;
6693 	for (i = strlen (templates_directory_uri); uri[i] != '\0'; i++) {
6694 		if (uri[i] == '/') {
6695 			num_levels++;
6696 		}
6697 	}
6698 
6699 	if (num_levels > MAX_MENU_LEVELS) {
6700 		return FALSE;
6701 	}
6702 
6703 	return TRUE;
6704 }
6705 
6706 static gboolean
update_directory_in_templates_menu(NemoView * view,const char * templates_directory_uri,NemoDirectory * directory)6707 update_directory_in_templates_menu (NemoView *view,
6708 				    const char *templates_directory_uri,
6709 				    NemoDirectory *directory)
6710 {
6711 	char *menu_path, *popup_bg_path;
6712 	GList *file_list, *filtered, *node;
6713 	gboolean any_templates;
6714 	NemoFile *file;
6715 	NemoDirectory *dir;
6716 	char *escaped_path;
6717 	char *uri;
6718 	int num;
6719 
6720 	/* We know this directory belongs to the template dir, so it must exist */
6721 	g_assert (templates_directory_uri);
6722 
6723 	uri = nemo_directory_get_uri (directory);
6724 	escaped_path = escape_action_path (uri + strlen (templates_directory_uri));
6725 	g_free (uri);
6726 	menu_path = g_strconcat (NEMO_VIEW_MENU_PATH_NEW_DOCUMENTS_PLACEHOLDER,
6727 				 escaped_path,
6728 				 NULL);
6729 	popup_bg_path = g_strconcat (NEMO_VIEW_POPUP_PATH_BACKGROUND_NEW_DOCUMENTS_PLACEHOLDER,
6730 				     escaped_path,
6731 				     NULL);
6732 	g_free (escaped_path);
6733 
6734 	file_list = nemo_directory_get_file_list (directory);
6735 	filtered = nemo_file_list_filter_hidden (file_list, FALSE);
6736 	nemo_file_list_free (file_list);
6737 
6738 	file_list = nemo_file_list_sort_by_display_name (filtered);
6739 
6740 	num = 0;
6741 	any_templates = FALSE;
6742 	for (node = file_list; num < TEMPLATE_LIMIT && node != NULL; node = node->next, num++) {
6743 		file = node->data;
6744 
6745 		if (nemo_file_is_directory (file)) {
6746 			uri = nemo_file_get_uri (file);
6747 			if (directory_belongs_in_templates_menu (templates_directory_uri, uri)) {
6748 				dir = nemo_directory_get_by_uri (uri);
6749 				add_directory_to_templates_directory_list (view, dir);
6750 				nemo_directory_unref (dir);
6751 
6752 				add_submenu_to_directory_menus (view,
6753 								view->details->templates_action_group,
6754 								view->details->templates_merge_id,
6755 								file, menu_path, NULL, popup_bg_path);
6756 
6757 				any_templates = TRUE;
6758 			}
6759 			g_free (uri);
6760 		} else if (nemo_file_can_read (file)) {
6761 			add_template_to_templates_menus (view, file, menu_path, popup_bg_path);
6762 			any_templates = TRUE;
6763 		}
6764 	}
6765 
6766 	nemo_file_list_free (file_list);
6767 
6768 	g_free (popup_bg_path);
6769 	g_free (menu_path);
6770 
6771 	return any_templates;
6772 }
6773 
6774 
6775 
6776 static void
update_templates_menu(NemoView * view)6777 update_templates_menu (NemoView *view)
6778 {
6779 	gboolean any_templates;
6780 	GList *sorted_copy, *node;
6781 	NemoDirectory *directory;
6782 	GtkUIManager *ui_manager;
6783 	char *uri;
6784 	GtkAction *action;
6785 	char *templates_directory_uri;
6786 
6787 	if (nemo_should_use_templates_directory ()) {
6788 		templates_directory_uri = nemo_get_templates_directory_uri ();
6789 	} else {
6790 		templates_directory_uri = NULL;
6791 	}
6792 
6793 	/* There is a race condition here.  If we don't mark the scripts menu as
6794 	   valid before we begin our task then we can lose template menu updates that
6795 	   occur before we finish. */
6796 	view->details->templates_invalid = FALSE;
6797 
6798 	ui_manager = nemo_window_get_ui_manager (view->details->window);
6799 	nemo_ui_unmerge_ui (ui_manager,
6800 				&view->details->templates_merge_id,
6801 				&view->details->templates_action_group);
6802 
6803 	nemo_ui_prepare_merge_ui (ui_manager,
6804 				      "TemplatesGroup",
6805 				      &view->details->templates_merge_id,
6806 				      &view->details->templates_action_group);
6807 
6808 	/* As we walk through the directories, remove any that no longer belong. */
6809 	any_templates = FALSE;
6810 	sorted_copy = nemo_directory_list_sort_by_uri
6811 		(nemo_directory_list_copy (view->details->templates_directory_list));
6812 	for (node = sorted_copy; node != NULL; node = node->next) {
6813 		directory = node->data;
6814 
6815 		uri = nemo_directory_get_uri (directory);
6816 		if (!directory_belongs_in_templates_menu (templates_directory_uri, uri)) {
6817 			remove_directory_from_templates_directory_list (view, directory);
6818 		} else if (update_directory_in_templates_menu (view,
6819 							       templates_directory_uri,
6820 							       directory)) {
6821 			any_templates = TRUE;
6822 		}
6823 		g_free (uri);
6824 	}
6825 	nemo_directory_list_free (sorted_copy);
6826 
6827 	action = gtk_action_group_get_action (view->details->dir_action_group, NEMO_ACTION_NO_TEMPLATES);
6828 	gtk_action_set_visible (action, !any_templates);
6829 
6830 	g_free (templates_directory_uri);
6831 }
6832 
6833 static GtkMenu *
create_popup_menu(NemoView * view,const char * popup_path)6834 create_popup_menu (NemoView *view, const char *popup_path)
6835 {
6836 	GtkWidget *menu;
6837 
6838 	menu = gtk_ui_manager_get_widget (nemo_window_get_ui_manager (view->details->window),
6839 					  popup_path);
6840 	gtk_menu_set_screen (GTK_MENU (menu),
6841 			     gtk_widget_get_screen (GTK_WIDGET (view)));
6842 	gtk_widget_show (GTK_WIDGET (menu));
6843 
6844 	return GTK_MENU (menu);
6845 }
6846 
6847 static void
copy_or_cut_files(NemoView * view,GList * clipboard_contents,gboolean cut)6848 copy_or_cut_files (NemoView *view,
6849 		   GList           *clipboard_contents,
6850 		   gboolean         cut)
6851 {
6852 	int count;
6853 	char *status_string, *name;
6854 	NemoClipboardInfo info;
6855         GtkTargetList *target_list;
6856         GtkTargetEntry *targets;
6857         int n_targets;
6858 
6859 	info.files = clipboard_contents;
6860 	info.cut = cut;
6861 
6862         target_list = gtk_target_list_new (NULL, 0);
6863         gtk_target_list_add (target_list, copied_files_atom, 0, 0);
6864         gtk_target_list_add_uri_targets (target_list, 0);
6865         gtk_target_list_add_text_targets (target_list, 0);
6866 
6867         targets = gtk_target_table_new_from_list (target_list, &n_targets);
6868         gtk_target_list_unref (target_list);
6869 
6870 	gtk_clipboard_set_with_data (nemo_clipboard_get (GTK_WIDGET (view)),
6871 				     targets, n_targets,
6872 				     nemo_get_clipboard_callback, nemo_clear_clipboard_callback,
6873 				     NULL);
6874         gtk_target_table_free (targets, n_targets);
6875 
6876 	nemo_clipboard_monitor_set_clipboard_info (nemo_clipboard_monitor_get (), &info);
6877 
6878 	count = g_list_length (clipboard_contents);
6879 	if (count == 1) {
6880 		name = nemo_file_get_display_name (clipboard_contents->data);
6881 		if (cut) {
6882 			status_string = g_strdup_printf (_("\"%s\" will be moved "
6883 							   "if you select the Paste command"),
6884 							 name);
6885 		} else {
6886 			status_string = g_strdup_printf (_("\"%s\" will be copied "
6887 							   "if you select the Paste command"),
6888 							 name);
6889 		}
6890 		g_free (name);
6891 	} else {
6892 		if (cut) {
6893 			status_string = g_strdup_printf (ngettext("The %'d selected item will be moved "
6894 								  "if you select the Paste command",
6895 								  "The %'d selected items will be moved "
6896 								  "if you select the Paste command",
6897 								  count),
6898 							 count);
6899 		} else {
6900 			status_string = g_strdup_printf (ngettext("The %'d selected item will be copied "
6901 								  "if you select the Paste command",
6902 								  "The %'d selected items will be copied "
6903 								  "if you select the Paste command",
6904 								  count),
6905 							 count);
6906 		}
6907 	}
6908 
6909 	nemo_window_slot_set_status (view->details->slot,
6910 					 status_string, NULL);
6911 	g_free (status_string);
6912 }
6913 
6914 static void
action_copy_files_callback(GtkAction * action,gpointer callback_data)6915 action_copy_files_callback (GtkAction *action,
6916 			    gpointer callback_data)
6917 {
6918 	NemoView *view;
6919 	GList *selection;
6920 
6921 	view = NEMO_VIEW (callback_data);
6922 
6923 	selection = nemo_view_get_selection_for_file_transfer (view);
6924 	copy_or_cut_files (view, selection, FALSE);
6925 	nemo_file_list_free (selection);
6926 }
6927 
6928 static void
move_copy_selection_to_next_pane(NemoView * view,int copy_action)6929 move_copy_selection_to_next_pane (NemoView *view,
6930 				  int copy_action)
6931 {
6932 	NemoWindowSlot *slot;
6933 	char *dest_location;
6934 
6935 	slot = nemo_window_get_extra_slot (nemo_view_get_nemo_window (view));
6936 	g_return_if_fail (slot != NULL);
6937 
6938 	dest_location = nemo_window_slot_get_current_uri (slot);
6939 	g_return_if_fail (dest_location != NULL);
6940 
6941 	move_copy_selection_to_location (view, copy_action, dest_location);
6942 }
6943 
6944 static void
action_copy_to_next_pane_callback(GtkAction * action,gpointer callback_data)6945 action_copy_to_next_pane_callback (GtkAction *action, gpointer callback_data)
6946 {
6947 	NemoView *view;
6948 
6949 	view = NEMO_VIEW (callback_data);
6950 	move_copy_selection_to_next_pane (view,
6951 					  GDK_ACTION_COPY);
6952 }
6953 
6954 static void
action_move_to_next_pane_callback(GtkAction * action,gpointer callback_data)6955 action_move_to_next_pane_callback (GtkAction *action, gpointer callback_data)
6956 {
6957 	NemoWindowSlot *slot;
6958 	char *dest_location;
6959 	NemoView *view;
6960 
6961 	view = NEMO_VIEW (callback_data);
6962 
6963 	slot = nemo_window_get_extra_slot (nemo_view_get_nemo_window (view));
6964 	g_return_if_fail (slot != NULL);
6965 
6966 	dest_location = nemo_window_slot_get_current_uri (slot);
6967 	g_return_if_fail (dest_location != NULL);
6968 
6969 	move_copy_selection_to_location (view, GDK_ACTION_MOVE, dest_location);
6970 }
6971 
6972 static void
action_copy_to_home_callback(GtkAction * action,gpointer callback_data)6973 action_copy_to_home_callback (GtkAction *action, gpointer callback_data)
6974 {
6975 	NemoView *view;
6976 	char *dest_location;
6977 
6978 	view = NEMO_VIEW (callback_data);
6979 
6980 	dest_location = nemo_get_home_directory_uri ();
6981 	move_copy_selection_to_location (view, GDK_ACTION_COPY, dest_location);
6982 	g_free (dest_location);
6983 }
6984 
6985 static void
action_move_to_home_callback(GtkAction * action,gpointer callback_data)6986 action_move_to_home_callback (GtkAction *action, gpointer callback_data)
6987 {
6988 	NemoView *view;
6989 	char *dest_location;
6990 
6991 	view = NEMO_VIEW (callback_data);
6992 
6993 	dest_location = nemo_get_home_directory_uri ();
6994 	move_copy_selection_to_location (view, GDK_ACTION_MOVE, dest_location);
6995 	g_free (dest_location);
6996 }
6997 
6998 static void
action_copy_to_desktop_callback(GtkAction * action,gpointer callback_data)6999 action_copy_to_desktop_callback (GtkAction *action, gpointer callback_data)
7000 {
7001 	NemoView *view;
7002 	char *dest_location;
7003 
7004 	view = NEMO_VIEW (callback_data);
7005 
7006 	dest_location = nemo_get_desktop_directory_uri ();
7007 	move_copy_selection_to_location (view, GDK_ACTION_COPY, dest_location);
7008 	g_free (dest_location);
7009 }
7010 
7011 static void
action_move_to_desktop_callback(GtkAction * action,gpointer callback_data)7012 action_move_to_desktop_callback (GtkAction *action, gpointer callback_data)
7013 {
7014 	NemoView *view;
7015 	char *dest_location;
7016 
7017 	view = NEMO_VIEW (callback_data);
7018 
7019 	dest_location = nemo_get_desktop_directory_uri ();
7020 	move_copy_selection_to_location (view, GDK_ACTION_MOVE, dest_location);
7021 	g_free (dest_location);
7022 }
7023 
7024 static void
browse_move_to_response_cb(GtkDialog * dialog,gint response,NemoView * view)7025 browse_move_to_response_cb (GtkDialog *dialog, gint response, NemoView *view)
7026 {
7027     gchar *uri;
7028 
7029     switch (response) {
7030         case GTK_RESPONSE_OK:
7031             uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
7032             move_copy_selection_to_location (view, GDK_ACTION_MOVE, uri);
7033             g_free (uri);
7034             break;
7035         case GTK_RESPONSE_CANCEL:
7036         default:
7037             break;
7038     }
7039 
7040     gtk_widget_destroy (GTK_WIDGET (dialog));
7041 }
7042 
7043 static void
browse_copy_to_response_cb(GtkDialog * dialog,gint response,NemoView * view)7044 browse_copy_to_response_cb (GtkDialog *dialog, gint response, NemoView *view)
7045 {
7046     gchar *uri;
7047 
7048     switch (response) {
7049         case GTK_RESPONSE_OK:
7050             uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
7051             move_copy_selection_to_location (view, GDK_ACTION_COPY, uri);
7052             g_free (uri);
7053             break;
7054         case GTK_RESPONSE_CANCEL:
7055         default:
7056             break;
7057     }
7058 
7059     gtk_widget_destroy (GTK_WIDGET (dialog));
7060 }
7061 
7062 static void
action_browse_for_move_to_folder_callback(GtkAction * action,gpointer callback_data)7063 action_browse_for_move_to_folder_callback (GtkAction *action, gpointer callback_data)
7064 {
7065     GtkWidget *dialog;
7066     NemoView *view;
7067 
7068     view = NEMO_VIEW (callback_data);
7069 
7070     dialog = gtk_file_chooser_dialog_new (_("Select Target Folder For Move"),
7071                                           nemo_view_get_containing_window (view),
7072                                           GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
7073                                           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
7074                                           GTK_STOCK_OPEN, GTK_RESPONSE_OK,
7075                                           NULL);
7076 
7077     gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), FALSE);
7078 
7079     g_signal_connect (dialog, "response",
7080                       G_CALLBACK (browse_move_to_response_cb), view);
7081 
7082     gtk_widget_show (dialog);
7083 }
7084 
7085 static void
action_browse_for_copy_to_folder_callback(GtkAction * action,gpointer callback_data)7086 action_browse_for_copy_to_folder_callback (GtkAction *action, gpointer callback_data)
7087 {
7088     GtkWidget *dialog;
7089     NemoView *view;
7090 
7091     view = NEMO_VIEW (callback_data);
7092 
7093     dialog = gtk_file_chooser_dialog_new (_("Select Target Folder For Copy"),
7094                                           nemo_view_get_containing_window (view),
7095                                           GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
7096                                           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
7097                                           GTK_STOCK_OPEN, GTK_RESPONSE_OK,
7098                                           NULL);
7099 
7100     gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog), FALSE);
7101 
7102     g_signal_connect (dialog, "response",
7103                       G_CALLBACK (browse_copy_to_response_cb), view);
7104 
7105     gtk_widget_show (dialog);
7106 }
7107 
7108 static void
action_cut_files_callback(GtkAction * action,gpointer callback_data)7109 action_cut_files_callback (GtkAction *action,
7110 			   gpointer callback_data)
7111 {
7112 	NemoView *view;
7113 	GList *selection;
7114 
7115 	view = NEMO_VIEW (callback_data);
7116 
7117 	selection = nemo_view_get_selection_for_file_transfer (view);
7118 	copy_or_cut_files (view, selection, TRUE);
7119 	nemo_file_list_free (selection);
7120 }
7121 
7122 static void
paste_clipboard_data(NemoView * view,GtkSelectionData * selection_data,char * destination_uri)7123 paste_clipboard_data (NemoView *view,
7124 		      GtkSelectionData *selection_data,
7125 		      char *destination_uri)
7126 {
7127 	gboolean cut;
7128 	GList *item_uris;
7129 
7130 	cut = FALSE;
7131 	item_uris = nemo_clipboard_get_uri_list_from_selection_data (selection_data, &cut,
7132 									 copied_files_atom);
7133 
7134 	if (item_uris == NULL|| destination_uri == NULL) {
7135 		nemo_window_slot_set_status (view->details->slot,
7136 						 _("There is nothing on the clipboard to paste."),
7137 						 NULL);
7138 	} else {
7139 		nemo_view_move_copy_items (view, item_uris, NULL, destination_uri,
7140 					       cut ? GDK_ACTION_MOVE : GDK_ACTION_COPY,
7141 					       0, 0);
7142 
7143 		/* If items are cut then remove from clipboard */
7144 		if (cut) {
7145 			gtk_clipboard_clear (nemo_clipboard_get (GTK_WIDGET (view)));
7146 		}
7147 
7148 		g_list_free_full (item_uris, g_free);
7149 	}
7150 }
7151 
7152 static void
paste_clipboard_received_callback(GtkClipboard * clipboard,GtkSelectionData * selection_data,gpointer data)7153 paste_clipboard_received_callback (GtkClipboard     *clipboard,
7154 				   GtkSelectionData *selection_data,
7155 				   gpointer          data)
7156 {
7157 	NemoView *view;
7158 	char *view_uri;
7159 
7160 	view = NEMO_VIEW (data);
7161 
7162 	view_uri = nemo_view_get_backing_uri (view);
7163 
7164 	if (view->details->window != NULL) {
7165 		paste_clipboard_data (view, selection_data, view_uri);
7166 	}
7167 
7168 	g_free (view_uri);
7169 
7170 	g_object_unref (view);
7171 }
7172 
7173 typedef struct {
7174 	NemoView *view;
7175 	NemoFile *target;
7176 } PasteIntoData;
7177 
7178 static void
paste_into_clipboard_received_callback(GtkClipboard * clipboard,GtkSelectionData * selection_data,gpointer callback_data)7179 paste_into_clipboard_received_callback (GtkClipboard     *clipboard,
7180 					GtkSelectionData *selection_data,
7181 					gpointer          callback_data)
7182 {
7183 	PasteIntoData *data;
7184 	NemoView *view;
7185 	char *directory_uri;
7186 
7187 	data = (PasteIntoData *) callback_data;
7188 
7189 	view = NEMO_VIEW (data->view);
7190 
7191 	if (view->details->window != NULL) {
7192 		directory_uri = nemo_file_get_activation_uri (data->target);
7193 
7194 		paste_clipboard_data (view, selection_data, directory_uri);
7195 
7196 		g_free (directory_uri);
7197 	}
7198 
7199 	g_object_unref (view);
7200 	nemo_file_unref (data->target);
7201 	g_free (data);
7202 }
7203 
7204 static void
action_paste_files_callback(GtkAction * action,gpointer callback_data)7205 action_paste_files_callback (GtkAction *action,
7206 			     gpointer callback_data)
7207 {
7208 	NemoView *view;
7209 
7210 	view = NEMO_VIEW (callback_data);
7211 
7212 	g_object_ref (view);
7213 	gtk_clipboard_request_contents (nemo_clipboard_get (GTK_WIDGET (view)),
7214 					copied_files_atom,
7215 					paste_clipboard_received_callback,
7216 					view);
7217 }
7218 
7219 static void
paste_into(NemoView * view,NemoFile * target)7220 paste_into (NemoView *view,
7221 	    NemoFile *target)
7222 {
7223 	PasteIntoData *data;
7224 
7225 	g_assert (NEMO_IS_VIEW (view));
7226 	g_assert (NEMO_IS_FILE (target));
7227 
7228 	data = g_new (PasteIntoData, 1);
7229 
7230 	data->view = g_object_ref (view);
7231 	data->target = nemo_file_ref (target);
7232 
7233 	gtk_clipboard_request_contents (nemo_clipboard_get (GTK_WIDGET (view)),
7234 					copied_files_atom,
7235 					paste_into_clipboard_received_callback,
7236 					data);
7237 }
7238 
7239 static void
cb_open_as_root_watch(GPid pid,gint status,gpointer user_data)7240 cb_open_as_root_watch (GPid pid, gint status, gpointer user_data)
7241 {
7242     g_spawn_close_pid(pid);
7243 }
7244 
7245 static void
open_as_root(const gchar * path)7246 open_as_root (const gchar *path)
7247 {
7248     gchar *argv[4];
7249     argv[0] = (gchar *)"pkexec";
7250     argv[1] = (gchar *)"nemo";
7251     argv[2] = g_strdup (path);
7252     argv[3] = NULL;
7253     GPid pid;
7254     g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
7255                   NULL, NULL, &pid, NULL);
7256     g_child_watch_add(pid, (GChildWatchFunc)cb_open_as_root_watch, NULL);
7257     g_free (argv[2]);
7258 }
7259 
7260 static void
open_in_terminal(const gchar * path)7261 open_in_terminal (const gchar *path)
7262 {
7263     gchar *argv[2];
7264     argv[0] = g_settings_get_string (gnome_terminal_preferences,
7265 				     GNOME_DESKTOP_TERMINAL_EXEC);
7266     argv[1] = NULL;
7267     g_spawn_async(path, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL);
7268 }
7269 
7270 static void
action_paste_files_into_callback(GtkAction * action,gpointer callback_data)7271 action_paste_files_into_callback (GtkAction *action,
7272 				  gpointer callback_data)
7273 {
7274 	NemoView *view;
7275 	GList *selection;
7276 
7277 	view = NEMO_VIEW (callback_data);
7278 	selection = nemo_view_get_selection (view);
7279 	if (selection != NULL) {
7280 		paste_into (view, NEMO_FILE (selection->data));
7281 		nemo_file_list_free (selection);
7282 	}
7283 
7284 }
7285 
7286 static void
action_open_as_root_callback(GtkAction * action,gpointer callback_data)7287 action_open_as_root_callback (GtkAction *action,
7288 				  gpointer callback_data)
7289 {
7290 	NemoView *view;
7291 	GList *selection;
7292 
7293 	view = NEMO_VIEW (callback_data);
7294 	selection = nemo_view_get_selection (view);
7295 	if (selection != NULL) {
7296         gchar *path = nemo_file_get_path (NEMO_FILE (selection->data));
7297 		open_as_root (path);
7298 		nemo_file_list_free (selection);
7299         g_free (path);
7300 	} else {
7301         gchar *path;
7302         gchar *uri = nemo_view_get_uri (view);
7303         GFile *gfile = g_file_new_for_uri (uri);
7304         if (g_file_has_uri_scheme (gfile, "x-nemo-desktop")) {
7305             path = nemo_get_desktop_directory ();
7306         } else {
7307             path = g_file_get_path (gfile);
7308         }
7309         open_as_root (path);
7310         g_free (uri);
7311         g_free (path);
7312         g_object_unref (gfile);
7313     }
7314 
7315 }
7316 
7317 static void
action_follow_symlink_callback(GtkAction * action,gpointer callback_data)7318 action_follow_symlink_callback (GtkAction *action,
7319                                 gpointer callback_data)
7320 {
7321     NemoView *view;
7322     GList *selection;
7323 
7324     view = NEMO_VIEW (callback_data);
7325     selection = nemo_view_get_selection (view);
7326     if (nemo_file_is_symbolic_link (selection->data)) {
7327         gchar *uri = nemo_file_get_symbolic_link_target_uri (selection->data);
7328         gchar *view_uri = nemo_view_get_uri (view);
7329         GFile *location = g_file_new_for_uri (uri);
7330         GFile *parent = g_file_get_parent (location);
7331         GFile *current = g_file_new_for_uri (view_uri);
7332 
7333         if (g_file_equal (current, parent)) {
7334             nemo_view_scroll_to_file (view, uri);
7335             GList *l = NULL;
7336             l = g_list_append (l, nemo_file_get_existing (location));
7337             nemo_view_set_selection (view, l);
7338         } else {
7339             if (get_is_desktop_view (view)) {
7340                 nemo_mime_launch_fm_and_select_file (location);
7341             } else {
7342                 nemo_window_slot_open_location (view->details->slot, location, 0);
7343             }
7344         }
7345 
7346         g_free (uri);
7347         g_free (view_uri);
7348         g_object_unref (location);
7349         g_object_unref (parent);
7350         g_object_unref (current);
7351     }
7352 
7353     nemo_file_list_free (selection);
7354 }
7355 
7356 static void
action_open_containing_folder_callback(GtkAction * action,gpointer callback_data)7357 action_open_containing_folder_callback (GtkAction *action,
7358                                         gpointer callback_data)
7359 {
7360     NemoView *view;
7361     GList *selection;
7362     NemoFile *item;
7363     GFile *activation_location;
7364     NemoFile *activation_file;
7365     NemoFile *location;
7366 
7367     view = NEMO_VIEW (callback_data);
7368     selection = nemo_view_get_selection (view);
7369 
7370     item = NEMO_FILE (selection->data);
7371     activation_location = nemo_file_get_activation_location (item);
7372     activation_file = nemo_file_get (activation_location);
7373     location = nemo_file_get_parent (activation_file);
7374 
7375     nemo_view_activate_file (view, location, 0);
7376 
7377     nemo_file_unref (location);
7378     nemo_file_unref (activation_file);
7379     g_object_unref (activation_location);
7380 }
7381 
7382 static void
action_open_in_terminal_callback(GtkAction * action,gpointer callback_data)7383 action_open_in_terminal_callback(GtkAction *action,
7384 				  gpointer callback_data)
7385 {
7386 	NemoView *view;
7387 	GList *selection;
7388 
7389 	view = NEMO_VIEW (callback_data);
7390 	selection = nemo_view_get_selection (view);
7391 	if (selection != NULL) {
7392         gchar *path;
7393         if (nemo_file_is_directory (NEMO_FILE (selection->data))) {
7394             path = nemo_file_get_path (NEMO_FILE (selection->data));
7395         } else {
7396             NemoFile *location = nemo_file_get_parent (NEMO_FILE (selection->data));
7397             path = nemo_file_get_path (location);
7398             nemo_file_unref (location);
7399         }
7400         open_in_terminal (path);
7401         g_free (path);
7402 		nemo_file_list_free (selection);
7403 	} else {
7404         gchar *path;
7405         gchar *uri = nemo_view_get_uri (view);
7406         GFile *gfile = g_file_new_for_uri (uri);
7407         if (g_file_has_uri_scheme (gfile, "x-nemo-desktop")) {
7408             path = nemo_get_desktop_directory ();
7409         } else {
7410             path = g_file_get_path (gfile);
7411         }
7412         open_in_terminal (path);
7413         g_free (uri);
7414         g_free (path);
7415         g_object_unref (gfile);
7416     }
7417 }
7418 
7419 static void
invoke_external_bulk_rename_utility(NemoView * view,GList * selection)7420 invoke_external_bulk_rename_utility (NemoView *view,
7421 				     GList *selection)
7422 {
7423 	GString *cmd;
7424 	char *parameter;
7425 	char *quoted_parameter;
7426 	char *bulk_rename_tool;
7427 	GList *walk;
7428 	NemoFile *file;
7429 
7430 	/* assemble command line */
7431 	bulk_rename_tool = get_bulk_rename_tool ();
7432 	cmd = g_string_new (bulk_rename_tool);
7433 	g_free (bulk_rename_tool);
7434 	for (walk = selection; walk; walk = walk->next) {
7435 		file = walk->data;
7436 		parameter = nemo_file_get_uri (file);
7437 		quoted_parameter = g_shell_quote (parameter);
7438 		g_free (parameter);
7439 		cmd = g_string_append (cmd, " ");
7440 		cmd = g_string_append (cmd, quoted_parameter);
7441 		g_free (quoted_parameter);
7442 	}
7443 
7444         guint i = 0;
7445 
7446 	// Escape percents
7447 	for (i = 0; i < strlen(cmd->str); i++) {
7448 		if (cmd->str[i] == '%') {
7449 			g_string_insert_c(cmd, i++, '%');
7450 		}
7451 	}
7452 
7453 	/* spawning and error handling */
7454 	nemo_launch_application_from_command (gtk_widget_get_screen (GTK_WIDGET (view)),
7455 						  cmd->str, FALSE, NULL);
7456 	g_string_free (cmd, TRUE);
7457 }
7458 
7459 static void
real_action_undo(NemoView * view)7460 real_action_undo (NemoView *view)
7461 {
7462 	GtkWidget *toplevel;
7463 
7464 	toplevel = gtk_widget_get_toplevel (GTK_WIDGET (view));
7465 	nemo_file_undo_manager_undo (GTK_WINDOW (toplevel));
7466 }
7467 
7468 static void
real_action_redo(NemoView * view)7469 real_action_redo (NemoView *view)
7470 {
7471 	GtkWidget *toplevel;
7472 
7473 	toplevel = gtk_widget_get_toplevel (GTK_WIDGET (view));
7474 	nemo_file_undo_manager_redo (GTK_WINDOW (toplevel));
7475 }
7476 
7477 static void
action_undo_callback(GtkAction * action,gpointer callback_data)7478 action_undo_callback (GtkAction *action,
7479 		      gpointer callback_data)
7480 {
7481 	real_action_undo (NEMO_VIEW (callback_data));
7482 }
7483 
7484 static void
action_redo_callback(GtkAction * action,gpointer callback_data)7485 action_redo_callback (GtkAction *action,
7486 		      gpointer callback_data)
7487 {
7488 	real_action_redo (NEMO_VIEW (callback_data));
7489 }
7490 
7491 static void
real_action_rename(NemoView * view,gboolean select_all)7492 real_action_rename (NemoView *view,
7493 		    gboolean select_all)
7494 {
7495 	NemoFile *file;
7496 	GList *selection;
7497 
7498 	g_assert (NEMO_IS_VIEW (view));
7499 
7500 	selection = nemo_view_get_selection (view);
7501 
7502 	if (selection_not_empty_in_menu_callback (view, selection)) {
7503 		/* If there is more than one file selected, invoke a batch renamer */
7504 		if (selection->next != NULL) {
7505 			if (have_bulk_rename_tool ()) {
7506 				invoke_external_bulk_rename_utility (view, selection);
7507 			}
7508 		} else {
7509 			file = NEMO_FILE (selection->data);
7510 			if (!select_all) {
7511 				/* directories don't have a file extension, so
7512 				 * they are always pre-selected as a whole */
7513 				select_all = nemo_file_is_directory (file);
7514 			}
7515 			NEMO_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->start_renaming_file (view, file, select_all);
7516 		}
7517 	}
7518 
7519 	nemo_file_list_free (selection);
7520 }
7521 
7522 static void
action_rename_callback(GtkAction * action,gpointer callback_data)7523 action_rename_callback (GtkAction *action,
7524 			gpointer callback_data)
7525 {
7526 	real_action_rename (NEMO_VIEW (callback_data), FALSE);
7527 }
7528 
7529 static void
action_rename_select_all_callback(GtkAction * action,gpointer callback_data)7530 action_rename_select_all_callback (GtkAction *action,
7531 				   gpointer callback_data)
7532 {
7533 	real_action_rename (NEMO_VIEW (callback_data), TRUE);
7534 }
7535 
7536 static void
file_mount_callback(NemoFile * file,GFile * result_location,GError * error,gpointer callback_data)7537 file_mount_callback (NemoFile  *file,
7538 		     GFile         *result_location,
7539 		     GError        *error,
7540 		     gpointer       callback_data)
7541 {
7542 	if (error != NULL &&
7543 	    (error->domain != G_IO_ERROR ||
7544 	     (error->code != G_IO_ERROR_CANCELLED &&
7545 	      error->code != G_IO_ERROR_FAILED_HANDLED &&
7546 	      error->code != G_IO_ERROR_ALREADY_MOUNTED))) {
7547 		eel_show_error_dialog (_("Unable to mount location"),
7548 				       error->message, NULL);
7549 	}
7550 }
7551 
7552 static void
file_unmount_callback(NemoFile * file,GFile * result_location,GError * error,gpointer callback_data)7553 file_unmount_callback (NemoFile  *file,
7554 		       GFile         *result_location,
7555 		       GError        *error,
7556 		       gpointer       callback_data)
7557 {
7558 	NemoView *view;
7559 
7560 	view = NEMO_VIEW (callback_data);
7561 	g_object_unref (view);
7562 
7563 	if (error != NULL &&
7564 	    (error->domain != G_IO_ERROR ||
7565 	     (error->code != G_IO_ERROR_CANCELLED &&
7566 	      error->code != G_IO_ERROR_FAILED_HANDLED))) {
7567 		eel_show_error_dialog (_("Unable to unmount location"),
7568 				       error->message, NULL);
7569 	}
7570 }
7571 
7572 static void
file_eject_callback(NemoFile * file,GFile * result_location,GError * error,gpointer callback_data)7573 file_eject_callback (NemoFile  *file,
7574 		     GFile         *result_location,
7575 		     GError        *error,
7576 		     gpointer       callback_data)
7577 {
7578 	NemoView *view;
7579 
7580 	view = NEMO_VIEW (callback_data);
7581 	g_object_unref (view);
7582 
7583 	if (error != NULL &&
7584 	    (error->domain != G_IO_ERROR ||
7585 	     (error->code != G_IO_ERROR_CANCELLED &&
7586 	      error->code != G_IO_ERROR_FAILED_HANDLED))) {
7587 		eel_show_error_dialog (_("Unable to eject location"),
7588 				       error->message, NULL);
7589 	}
7590 }
7591 
7592 static void
file_stop_callback(NemoFile * file,GFile * result_location,GError * error,gpointer callback_data)7593 file_stop_callback (NemoFile  *file,
7594 		    GFile         *result_location,
7595 		    GError        *error,
7596 		    gpointer       callback_data)
7597 {
7598 	if (error != NULL &&
7599 	    (error->domain != G_IO_ERROR ||
7600 	     (error->code != G_IO_ERROR_CANCELLED &&
7601 	      error->code != G_IO_ERROR_FAILED_HANDLED))) {
7602 		eel_show_error_dialog (_("Unable to stop drive"),
7603 				       error->message, NULL);
7604 	}
7605 }
7606 
7607 static void
action_mount_volume_callback(GtkAction * action,gpointer data)7608 action_mount_volume_callback (GtkAction *action,
7609 			      gpointer data)
7610 {
7611 	NemoFile *file;
7612 	GList *selection, *l;
7613 	NemoView *view;
7614 	GMountOperation *mount_op;
7615 
7616         view = NEMO_VIEW (data);
7617 
7618 	selection = nemo_view_get_selection (view);
7619 	for (l = selection; l != NULL; l = l->next) {
7620 		file = NEMO_FILE (l->data);
7621 
7622 		if (nemo_file_can_mount (file)) {
7623 			mount_op = gtk_mount_operation_new (nemo_view_get_containing_window (view));
7624 			g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION);
7625 			nemo_file_mount (file, mount_op, NULL,
7626 					     file_mount_callback, NULL);
7627 			g_object_unref (mount_op);
7628 		}
7629 	}
7630 	nemo_file_list_free (selection);
7631 }
7632 
7633 static void
action_unmount_volume_callback(GtkAction * action,gpointer data)7634 action_unmount_volume_callback (GtkAction *action,
7635 				gpointer data)
7636 {
7637 	NemoFile *file;
7638 	GList *selection, *l;
7639 	NemoView *view;
7640 
7641         view = NEMO_VIEW (data);
7642 
7643 	selection = nemo_view_get_selection (view);
7644 
7645 	for (l = selection; l != NULL; l = l->next) {
7646 		file = NEMO_FILE (l->data);
7647 		if (nemo_file_can_unmount (file)) {
7648 			GMountOperation *mount_op;
7649 			mount_op = gtk_mount_operation_new (nemo_view_get_containing_window (view));
7650 			nemo_file_unmount (file, mount_op, NULL,
7651 					       file_unmount_callback, g_object_ref (view));
7652 			g_object_unref (mount_op);
7653 		}
7654 	}
7655 	nemo_file_list_free (selection);
7656 }
7657 
7658 static void
action_eject_volume_callback(GtkAction * action,gpointer data)7659 action_eject_volume_callback (GtkAction *action,
7660 			      gpointer data)
7661 {
7662 	NemoFile *file;
7663 	GList *selection, *l;
7664 	NemoView *view;
7665 
7666         view = NEMO_VIEW (data);
7667 
7668 	selection = nemo_view_get_selection (view);
7669 	for (l = selection; l != NULL; l = l->next) {
7670 		file = NEMO_FILE (l->data);
7671 
7672 		if (nemo_file_can_eject (file)) {
7673 			GMountOperation *mount_op;
7674 			mount_op = gtk_mount_operation_new (nemo_view_get_containing_window (view));
7675 			nemo_file_eject (file, mount_op, NULL,
7676 					     file_eject_callback, g_object_ref (view));
7677 			g_object_unref (mount_op);
7678 		}
7679 	}
7680 	nemo_file_list_free (selection);
7681 }
7682 
7683 static void
file_start_callback(NemoFile * file,GFile * result_location,GError * error,gpointer callback_data)7684 file_start_callback (NemoFile  *file,
7685 		     GFile         *result_location,
7686 		     GError        *error,
7687 		     gpointer       callback_data)
7688 {
7689 	if (error != NULL &&
7690 	    (error->domain != G_IO_ERROR ||
7691 	     (error->code != G_IO_ERROR_CANCELLED &&
7692 	      error->code != G_IO_ERROR_FAILED_HANDLED &&
7693 	      error->code != G_IO_ERROR_ALREADY_MOUNTED))) {
7694 		eel_show_error_dialog (_("Unable to start location"),
7695 				       error->message, NULL);
7696 	}
7697 }
7698 
7699 static void
action_start_volume_callback(GtkAction * action,gpointer data)7700 action_start_volume_callback (GtkAction *action,
7701 			      gpointer   data)
7702 {
7703 	NemoFile *file;
7704 	GList *selection, *l;
7705 	NemoView *view;
7706 	GMountOperation *mount_op;
7707 
7708         view = NEMO_VIEW (data);
7709 
7710 	selection = nemo_view_get_selection (view);
7711 	for (l = selection; l != NULL; l = l->next) {
7712 		file = NEMO_FILE (l->data);
7713 
7714 		if (nemo_file_can_start (file) || nemo_file_can_start_degraded (file)) {
7715 			mount_op = gtk_mount_operation_new (nemo_view_get_containing_window (view));
7716 			nemo_file_start (file, mount_op, NULL,
7717 					     file_start_callback, NULL);
7718 			g_object_unref (mount_op);
7719 		}
7720 	}
7721 	nemo_file_list_free (selection);
7722 }
7723 
7724 static void
action_stop_volume_callback(GtkAction * action,gpointer data)7725 action_stop_volume_callback (GtkAction *action,
7726 			     gpointer   data)
7727 {
7728 	NemoFile *file;
7729 	GList *selection, *l;
7730 	NemoView *view;
7731 
7732         view = NEMO_VIEW (data);
7733 
7734 	selection = nemo_view_get_selection (view);
7735 	for (l = selection; l != NULL; l = l->next) {
7736 		file = NEMO_FILE (l->data);
7737 
7738 		if (nemo_file_can_stop (file)) {
7739 			GMountOperation *mount_op;
7740 			mount_op = gtk_mount_operation_new (nemo_view_get_containing_window (view));
7741 			nemo_file_stop (file, mount_op, NULL,
7742 					    file_stop_callback, NULL);
7743 			g_object_unref (mount_op);
7744 		}
7745 	}
7746 	nemo_file_list_free (selection);
7747 }
7748 
7749 static void
action_detect_media_callback(GtkAction * action,gpointer data)7750 action_detect_media_callback (GtkAction *action,
7751 			      gpointer   data)
7752 {
7753 	NemoFile *file;
7754 	GList *selection, *l;
7755 	NemoView *view;
7756 
7757         view = NEMO_VIEW (data);
7758 
7759 	selection = nemo_view_get_selection (view);
7760 	for (l = selection; l != NULL; l = l->next) {
7761 		file = NEMO_FILE (l->data);
7762 
7763 		if (nemo_file_can_poll_for_media (file) && !nemo_file_is_media_check_automatic (file)) {
7764 			nemo_file_poll_for_media (file);
7765 		}
7766 	}
7767 	nemo_file_list_free (selection);
7768 }
7769 
7770 static void
action_self_mount_volume_callback(GtkAction * action,gpointer data)7771 action_self_mount_volume_callback (GtkAction *action,
7772 				   gpointer data)
7773 {
7774 	NemoFile *file;
7775 	NemoView *view;
7776 	GMountOperation *mount_op;
7777 
7778 	view = NEMO_VIEW (data);
7779 
7780 	file = nemo_view_get_directory_as_file (view);
7781 	if (file == NULL) {
7782 		return;
7783 	}
7784 
7785 	mount_op = gtk_mount_operation_new (nemo_view_get_containing_window (view));
7786 	g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION);
7787 	nemo_file_mount (file, mount_op, NULL, file_mount_callback, NULL);
7788 	g_object_unref (mount_op);
7789 }
7790 
7791 static void
action_self_unmount_volume_callback(GtkAction * action,gpointer data)7792 action_self_unmount_volume_callback (GtkAction *action,
7793 				     gpointer data)
7794 {
7795 	NemoFile *file;
7796 	NemoView *view;
7797 	GMountOperation *mount_op;
7798 
7799 	view = NEMO_VIEW (data);
7800 
7801 	file = nemo_view_get_directory_as_file (view);
7802 	if (file == NULL) {
7803 		return;
7804 	}
7805 
7806 	mount_op = gtk_mount_operation_new (nemo_view_get_containing_window (view));
7807 	nemo_file_unmount (file, mount_op, NULL, file_unmount_callback, g_object_ref (view));
7808 	g_object_unref (mount_op);
7809 }
7810 
7811 static void
action_self_eject_volume_callback(GtkAction * action,gpointer data)7812 action_self_eject_volume_callback (GtkAction *action,
7813 				   gpointer data)
7814 {
7815 	NemoFile *file;
7816 	NemoView *view;
7817 	GMountOperation *mount_op;
7818 
7819 	view = NEMO_VIEW (data);
7820 
7821 	file = nemo_view_get_directory_as_file (view);
7822 	if (file == NULL) {
7823 		return;
7824 	}
7825 
7826 	mount_op = gtk_mount_operation_new (nemo_view_get_containing_window (view));
7827 	nemo_file_eject (file, mount_op, NULL, file_eject_callback, g_object_ref (view));
7828 	g_object_unref (mount_op);
7829 }
7830 
7831 static void
action_self_start_volume_callback(GtkAction * action,gpointer data)7832 action_self_start_volume_callback (GtkAction *action,
7833 				   gpointer   data)
7834 {
7835 	NemoFile *file;
7836 	NemoView *view;
7837 	GMountOperation *mount_op;
7838 
7839 	view = NEMO_VIEW (data);
7840 
7841 	file = nemo_view_get_directory_as_file (view);
7842 	if (file == NULL) {
7843 		return;
7844 	}
7845 
7846 	mount_op = gtk_mount_operation_new (nemo_view_get_containing_window (view));
7847 	nemo_file_start (file, mount_op, NULL, file_start_callback, NULL);
7848 	g_object_unref (mount_op);
7849 }
7850 
7851 static void
action_self_stop_volume_callback(GtkAction * action,gpointer data)7852 action_self_stop_volume_callback (GtkAction *action,
7853 				  gpointer   data)
7854 {
7855 	NemoFile *file;
7856 	NemoView *view;
7857 	GMountOperation *mount_op;
7858 
7859 	view = NEMO_VIEW (data);
7860 
7861 	file = nemo_view_get_directory_as_file (view);
7862 	if (file == NULL) {
7863 		return;
7864 	}
7865 
7866 	mount_op = gtk_mount_operation_new (nemo_view_get_containing_window (view));
7867 	nemo_file_stop (file, mount_op, NULL,
7868 			    file_stop_callback, NULL);
7869 	g_object_unref (mount_op);
7870 }
7871 
7872 static void
action_self_detect_media_callback(GtkAction * action,gpointer data)7873 action_self_detect_media_callback (GtkAction *action,
7874 				   gpointer   data)
7875 {
7876 	NemoFile *file;
7877 	NemoView *view;
7878 
7879 	view = NEMO_VIEW (data);
7880 
7881 	file = nemo_view_get_directory_as_file (view);
7882 	if (file == NULL) {
7883 		return;
7884 	}
7885 
7886 	nemo_file_poll_for_media (file);
7887 }
7888 
7889 static void
action_location_mount_volume_callback(GtkAction * action,gpointer data)7890 action_location_mount_volume_callback (GtkAction *action,
7891 				       gpointer data)
7892 {
7893 	NemoFile *file;
7894 	NemoView *view;
7895 	GMountOperation *mount_op;
7896 
7897 	view = NEMO_VIEW (data);
7898 
7899 	file = view->details->location_popup_directory_as_file;
7900 	if (file == NULL) {
7901 		return;
7902 	}
7903 
7904 	mount_op = gtk_mount_operation_new (nemo_view_get_containing_window (view));
7905 	g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION);
7906 	nemo_file_mount (file, mount_op, NULL, file_mount_callback, NULL);
7907 	g_object_unref (mount_op);
7908 }
7909 
7910 static void
action_location_unmount_volume_callback(GtkAction * action,gpointer data)7911 action_location_unmount_volume_callback (GtkAction *action,
7912 					 gpointer data)
7913 {
7914 	NemoFile *file;
7915 	NemoView *view;
7916 	GMountOperation *mount_op;
7917 
7918 	view = NEMO_VIEW (data);
7919 
7920 	file = view->details->location_popup_directory_as_file;
7921 	if (file == NULL) {
7922 		return;
7923 	}
7924 
7925 	mount_op = gtk_mount_operation_new (nemo_view_get_containing_window (view));
7926 	nemo_file_unmount (file, mount_op, NULL,
7927 			       file_unmount_callback, g_object_ref (view));
7928 	g_object_unref (mount_op);
7929 }
7930 
7931 static void
action_location_eject_volume_callback(GtkAction * action,gpointer data)7932 action_location_eject_volume_callback (GtkAction *action,
7933 				       gpointer data)
7934 {
7935 	NemoFile *file;
7936 	NemoView *view;
7937 	GMountOperation *mount_op;
7938 
7939 	view = NEMO_VIEW (data);
7940 
7941 	file = view->details->location_popup_directory_as_file;
7942 	if (file == NULL) {
7943 		return;
7944 	}
7945 
7946 	mount_op = gtk_mount_operation_new (nemo_view_get_containing_window (view));
7947 	nemo_file_eject (file, mount_op, NULL,
7948 			     file_eject_callback, g_object_ref (view));
7949 	g_object_unref (mount_op);
7950 }
7951 
7952 static void
action_location_start_volume_callback(GtkAction * action,gpointer data)7953 action_location_start_volume_callback (GtkAction *action,
7954 				       gpointer   data)
7955 {
7956 	NemoFile *file;
7957 	NemoView *view;
7958 	GMountOperation *mount_op;
7959 
7960 	view = NEMO_VIEW (data);
7961 
7962 	file = view->details->location_popup_directory_as_file;
7963 	if (file == NULL) {
7964 		return;
7965 	}
7966 
7967 	mount_op = gtk_mount_operation_new (nemo_view_get_containing_window (view));
7968 	nemo_file_start (file, mount_op, NULL, file_start_callback, NULL);
7969 	g_object_unref (mount_op);
7970 }
7971 
7972 static void
action_location_stop_volume_callback(GtkAction * action,gpointer data)7973 action_location_stop_volume_callback (GtkAction *action,
7974 				      gpointer   data)
7975 {
7976 	NemoFile *file;
7977 	NemoView *view;
7978 	GMountOperation *mount_op;
7979 
7980 	view = NEMO_VIEW (data);
7981 
7982 	file = view->details->location_popup_directory_as_file;
7983 	if (file == NULL) {
7984 		return;
7985 	}
7986 
7987 	mount_op = gtk_mount_operation_new (nemo_view_get_containing_window (view));
7988 	nemo_file_stop (file, mount_op, NULL,
7989 			    file_stop_callback, NULL);
7990 	g_object_unref (mount_op);
7991 }
7992 
7993 static void
action_location_detect_media_callback(GtkAction * action,gpointer data)7994 action_location_detect_media_callback (GtkAction *action,
7995 				       gpointer   data)
7996 {
7997 	NemoFile *file;
7998 	NemoView *view;
7999 
8000 	view = NEMO_VIEW (data);
8001 
8002 	file = view->details->location_popup_directory_as_file;
8003 	if (file == NULL) {
8004 		return;
8005 	}
8006 
8007 	nemo_file_poll_for_media (file);
8008 }
8009 
8010 static void
connect_to_server_response_callback(GtkDialog * dialog,int response_id,gpointer data)8011 connect_to_server_response_callback (GtkDialog *dialog,
8012 				     int response_id,
8013 				     gpointer data)
8014 {
8015 #ifdef GIO_CONVERSION_DONE
8016 	GtkEntry *entry;
8017 	char *uri;
8018 	const char *name;
8019 	char *icon;
8020 
8021 	entry = GTK_ENTRY (data);
8022 
8023 	switch (response_id) {
8024 	case GTK_RESPONSE_OK:
8025 		uri = g_object_get_data (G_OBJECT (dialog), "link-uri");
8026 		icon = g_object_get_data (G_OBJECT (dialog), "link-icon");
8027 		name = gtk_entry_get_text (entry);
8028 		gnome_vfs_connect_to_server (uri, (char *)name, icon);
8029 		gtk_widget_destroy (GTK_WIDGET (dialog));
8030 		break;
8031 	case GTK_RESPONSE_NONE:
8032 	case GTK_RESPONSE_DELETE_EVENT:
8033 	case GTK_RESPONSE_CANCEL:
8034 		gtk_widget_destroy (GTK_WIDGET (dialog));
8035 		break;
8036 	default :
8037 		g_assert_not_reached ();
8038 	}
8039 #endif
8040 	/* FIXME: the above code should make a server connection permanent */
8041 	gtk_widget_destroy (GTK_WIDGET (dialog));
8042 }
8043 
8044 static void
entry_activate_callback(GtkEntry * entry,gpointer user_data)8045 entry_activate_callback (GtkEntry *entry,
8046 			 gpointer user_data)
8047 {
8048 	GtkDialog *dialog;
8049 
8050 	dialog = GTK_DIALOG (user_data);
8051 	gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
8052 }
8053 
8054 static void
action_connect_to_server_link_callback(GtkAction * action,gpointer data)8055 action_connect_to_server_link_callback (GtkAction *action,
8056 					gpointer data)
8057 {
8058 	NemoFile *file;
8059 	GList *selection;
8060 	NemoView *view;
8061 	char *uri;
8062 	NemoIconInfo *icon;
8063 	const char *icon_name;
8064 	char *name;
8065 	GtkWidget *dialog;
8066 	GtkWidget *label;
8067 	GtkWidget *entry;
8068 	GtkWidget *box;
8069 	char *title;
8070 
8071         view = NEMO_VIEW (data);
8072 
8073 	selection = nemo_view_get_selection (view);
8074 
8075 	if (g_list_length (selection) != 1) {
8076 		nemo_file_list_free (selection);
8077 		return;
8078 	}
8079 
8080 	file = NEMO_FILE (selection->data);
8081 
8082 	uri = nemo_file_get_activation_uri (file);
8083 	icon = nemo_file_get_icon (file, NEMO_ICON_SIZE_STANDARD, 0, gtk_widget_get_scale_factor (GTK_WIDGET (view)), 0);
8084 	icon_name = nemo_icon_info_get_used_name (icon);
8085 	name = nemo_file_get_display_name (file);
8086 
8087 	if (uri != NULL) {
8088 		title = g_strdup_printf (_("Connect to Server %s"), name);
8089 		dialog = gtk_dialog_new_with_buttons (title,
8090 						      nemo_view_get_containing_window (view),
8091 						      0,
8092 						      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
8093 						      _("_Connect"), GTK_RESPONSE_OK,
8094 						      NULL);
8095 
8096 		g_object_set_data_full (G_OBJECT (dialog), "link-uri", g_strdup (uri), g_free);
8097 		g_object_set_data_full (G_OBJECT (dialog), "link-icon", g_strdup (icon_name), g_free);
8098 
8099 		gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
8100 		gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 2);
8101 
8102 		box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
8103 		gtk_widget_show (box);
8104 		gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
8105 				    box, TRUE, TRUE, 0);
8106 
8107 		label = gtk_label_new_with_mnemonic (_("Link _name:"));
8108 		gtk_widget_show (label);
8109 
8110 		gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 12);
8111 
8112 		entry = gtk_entry_new ();
8113 		if (name) {
8114 			gtk_entry_set_text (GTK_ENTRY (entry), name);
8115 		}
8116 		g_signal_connect (entry,
8117 				  "activate",
8118 				  G_CALLBACK (entry_activate_callback),
8119 				  dialog);
8120 
8121 		gtk_widget_show (entry);
8122 		gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
8123 
8124 		gtk_box_pack_start (GTK_BOX (box), entry, TRUE, TRUE, 12);
8125 
8126 		gtk_dialog_set_default_response (GTK_DIALOG (dialog),
8127 						 GTK_RESPONSE_OK);
8128 		g_signal_connect (dialog, "response",
8129 				  G_CALLBACK (connect_to_server_response_callback),
8130 				  entry);
8131 		gtk_widget_show (dialog);
8132 	}
8133 
8134 	g_free (uri);
8135 	nemo_icon_info_unref (icon);
8136 	g_free (name);
8137 }
8138 
8139 static void
action_location_open_alternate_callback(GtkAction * action,gpointer callback_data)8140 action_location_open_alternate_callback (GtkAction *action,
8141 					 gpointer   callback_data)
8142 {
8143 	NemoView *view;
8144 	NemoFile *file;
8145 
8146 	view = NEMO_VIEW (callback_data);
8147 
8148 	file = view->details->location_popup_directory_as_file;
8149 	if (file == NULL) {
8150 		return;
8151 	}
8152 	nemo_view_activate_file (view,
8153 				     file,
8154 				     NEMO_WINDOW_OPEN_FLAG_NEW_WINDOW);
8155 }
8156 
8157 static void
action_location_open_in_new_tab_callback(GtkAction * action,gpointer callback_data)8158 action_location_open_in_new_tab_callback (GtkAction *action,
8159 					  gpointer   callback_data)
8160 {
8161 	NemoView *view;
8162 	NemoFile *file;
8163 
8164 	view = NEMO_VIEW (callback_data);
8165 
8166 	file = view->details->location_popup_directory_as_file;
8167 	if (file == NULL) {
8168 		return;
8169 	}
8170 
8171 	nemo_view_activate_file (view,
8172 				     file,
8173 				     NEMO_WINDOW_OPEN_FLAG_NEW_TAB);
8174 }
8175 
8176 static void
action_location_cut_callback(GtkAction * action,gpointer callback_data)8177 action_location_cut_callback (GtkAction *action,
8178 			      gpointer   callback_data)
8179 {
8180 	NemoView *view;
8181 	NemoFile *file;
8182 	GList *files;
8183 
8184 	view = NEMO_VIEW (callback_data);
8185 
8186 	file = view->details->location_popup_directory_as_file;
8187 	g_return_if_fail (file != NULL);
8188 
8189 	files = g_list_append (NULL, file);
8190 	copy_or_cut_files (view, files, TRUE);
8191 	g_list_free (files);
8192 }
8193 
8194 static void
action_location_copy_callback(GtkAction * action,gpointer callback_data)8195 action_location_copy_callback (GtkAction *action,
8196 			       gpointer   callback_data)
8197 {
8198 	NemoView *view;
8199 	NemoFile *file;
8200 	GList *files;
8201 
8202 	view = NEMO_VIEW (callback_data);
8203 
8204 	file = view->details->location_popup_directory_as_file;
8205 	g_return_if_fail (file != NULL);
8206 
8207 	files = g_list_append (NULL, file);
8208 	copy_or_cut_files (view, files, FALSE);
8209 	g_list_free (files);
8210 }
8211 
8212 static void
action_location_paste_files_into_callback(GtkAction * action,gpointer callback_data)8213 action_location_paste_files_into_callback (GtkAction *action,
8214 					   gpointer callback_data)
8215 {
8216 	NemoView *view;
8217 	NemoFile *file;
8218 
8219 	view = NEMO_VIEW (callback_data);
8220 
8221 	file = view->details->location_popup_directory_as_file;
8222 	g_return_if_fail (file != NULL);
8223 
8224 	paste_into (view, file);
8225 }
8226 
8227 static void
action_location_trash_callback(GtkAction * action,gpointer callback_data)8228 action_location_trash_callback (GtkAction *action,
8229 				gpointer   callback_data)
8230 {
8231 	NemoView *view;
8232 	NemoFile *file;
8233 	GList *files;
8234 
8235 	view = NEMO_VIEW (callback_data);
8236 
8237 	file = view->details->location_popup_directory_as_file;
8238 	g_return_if_fail (file != NULL);
8239 
8240 	files = g_list_append (NULL, file);
8241 	trash_or_delete_files (nemo_view_get_containing_window (view),
8242 			       files, TRUE,
8243 			       view);
8244 	g_list_free (files);
8245 }
8246 
8247 static void
action_location_delete_callback(GtkAction * action,gpointer callback_data)8248 action_location_delete_callback (GtkAction *action,
8249 				 gpointer   callback_data)
8250 {
8251 	NemoView *view;
8252 	NemoFile *file;
8253 	GFile *location;
8254 	GList *files;
8255 
8256 	view = NEMO_VIEW (callback_data);
8257 
8258 	file = view->details->location_popup_directory_as_file;
8259 	g_return_if_fail (file != NULL);
8260 
8261 	location = nemo_file_get_location (file);
8262 
8263 	files = g_list_append (NULL, location);
8264 	nemo_file_operations_delete (files, nemo_view_get_containing_window (view),
8265 					 NULL, NULL);
8266 
8267 	g_list_free_full (files, g_object_unref);
8268 }
8269 
8270 static void
action_location_restore_from_trash_callback(GtkAction * action,gpointer callback_data)8271 action_location_restore_from_trash_callback (GtkAction *action,
8272 					     gpointer callback_data)
8273 {
8274 	NemoView *view;
8275 	NemoFile *file;
8276 	GList l;
8277 
8278 	view = NEMO_VIEW (callback_data);
8279 	file = view->details->location_popup_directory_as_file;
8280 
8281 	l.prev = NULL;
8282 	l.next = NULL;
8283 	l.data = file;
8284 	nemo_restore_files_from_trash (&l,
8285 					   nemo_view_get_containing_window (view));
8286 }
8287 
8288 static void
nemo_view_init_show_hidden_files(NemoView * view)8289 nemo_view_init_show_hidden_files (NemoView *view)
8290 {
8291 	NemoWindowShowHiddenFilesMode mode;
8292 	gboolean show_hidden_changed;
8293 
8294 	if (view->details->ignore_hidden_file_preferences) {
8295 		return;
8296 	}
8297 
8298 	mode = nemo_window_get_hidden_files_mode (view->details->window);
8299 
8300     if (mode == NEMO_WINDOW_SHOW_HIDDEN_FILES_ENABLE) {
8301         show_hidden_changed = !view->details->show_hidden_files;
8302         view->details->show_hidden_files = TRUE;
8303     } else {
8304         show_hidden_changed = view->details->show_hidden_files;
8305         view->details->show_hidden_files = FALSE;
8306     }
8307 
8308     if (show_hidden_changed && (view->details->model != NULL)) {
8309         load_directory (view, view->details->model);
8310     }
8311 }
8312 
8313 static const GtkActionEntry directory_view_entries[] = {
8314   /* name, stock id, label */  { "New Documents", "document-new-symbolic", N_("Create New _Document") },
8315   /* name, stock id, label */  { "Open With", NULL, N_("Open Wit_h"),
8316 				 NULL, N_("Choose a program with which to open the selected item") },
8317   /* name, stock id */         { "Properties", "document-properties-symbolic",
8318   /* label, accelerator */       N_("_Properties"), "<alt>Return",
8319   /* tooltip */                  N_("View or modify the properties of each selected item"),
8320 				 G_CALLBACK (action_properties_callback) },
8321   /* name, stock id */         { "PropertiesAccel", NULL,
8322   /* label, accelerator */       "PropertiesAccel", "<control>I",
8323   /* tooltip */                  NULL,
8324 				 G_CALLBACK (action_properties_callback) },
8325   /* name, stock id */         { "New Folder", "folder-new-symbolic",
8326   /* label, accelerator */       N_("Create New _Folder"), "<control><shift>N",
8327   /* tooltip */                  N_("Create a new empty folder inside this folder"),
8328 				 G_CALLBACK (action_new_folder_callback) },
8329   /* name, stock id, label */  { "No Templates", NULL, N_("No templates installed") },
8330   /* name, stock id */         { "New Empty Document", NULL,
8331     /* translators: this is used to indicate that a document doesn't contain anything */
8332   /* label, accelerator */       N_("_Empty Document"), NULL,
8333   /* tooltip */                  N_("Create a new empty document inside this folder"),
8334 				 G_CALLBACK (action_new_empty_file_callback) },
8335   /* name, stock id */         { "Open", NULL,
8336   /* label, accelerator */       N_("_Open"), "<control>o",
8337   /* tooltip */                  N_("Open the selected item in this window"),
8338                  G_CALLBACK (action_open_callback) },
8339   /* name, stock id */         { "OpenAccel", NULL,
8340   /* label, accelerator */       "OpenAccel", "<alt>Down",
8341   /* tooltip */                  NULL,
8342 				 G_CALLBACK (action_open_callback) },
8343   /* name, stock id */         { "OpenAlternate", NULL,
8344   /* label, accelerator */       N_("Open in Navigation Window"), "<control><shift>o",
8345   /* tooltip */                  N_("Open each selected item in a navigation window"),
8346 				 G_CALLBACK (action_open_alternate_callback) },
8347   /* name, stock id */         { "OpenInNewTab", NULL,
8348   /* label, accelerator */       N_("Open in New _Tab"), "<control><shift>t",
8349   /* tooltip */                  N_("Open each selected item in a new tab"),
8350 				 G_CALLBACK (action_open_new_tab_callback) },
8351   /* name, stock id */         { NEMO_ACTION_OPEN_IN_TERMINAL, "utilities-terminal-symbolic",
8352   /* label, accelerator */       N_("Open in Terminal"), "",
8353   /* tooltip */                  N_("Open terminal in the selected folder"),
8354 				 G_CALLBACK (action_open_in_terminal_callback) },
8355   /* name, stock id */         { NEMO_ACTION_OPEN_AS_ROOT, "dialog-password-symbolic",
8356   /* label, accelerator */       N_("Open as Root"), "",
8357   /* tooltip */                  N_("Open the folder with administration privileges"),
8358 				 G_CALLBACK (action_open_as_root_callback) },
8359 
8360   /* name, stock id */         { NEMO_ACTION_FOLLOW_SYMLINK, "go-jump-symbolic",
8361   /* label, accelerator */       N_("Follow link to original file"), "",
8362   /* tooltip */                  N_("Navigate to the original file that this symbolic link points to"),
8363                  G_CALLBACK (action_follow_symlink_callback) },
8364   /* name, stock id */         { NEMO_ACTION_OPEN_CONTAINING_FOLDER, "go-jump-symbolic",
8365   /* label, accelerator */       N_("Open containing folder"), "<control><alt>O",
8366   /* tooltip */                  N_("Navigate to the folder that the selected item is stored in"),
8367                  G_CALLBACK (action_open_containing_folder_callback) },
8368   /* name, stock id */         { "OtherApplication1", NULL,
8369   /* label, accelerator */       N_("Other _Application..."), NULL,
8370   /* tooltip */                  N_("Choose another application with which to open the selected item"),
8371 				 G_CALLBACK (action_other_application_callback) },
8372   /* name, stock id */         { "OtherApplication2", NULL,
8373   /* label, accelerator */       N_("Open With Other _Application..."), NULL,
8374   /* tooltip */                  N_("Choose another application with which to open the selected item"),
8375 				 G_CALLBACK (action_other_application_callback) },
8376   /* name, stock id */         { "Empty Trash", NULL,
8377   /* label, accelerator */       N_("E_mpty Trash"), NULL,
8378   /* tooltip */                  N_("Delete all items in the Trash"),
8379 				 G_CALLBACK (action_empty_trash_callback) },
8380   /* name, stock id */         { "Cut", "edit-cut-symbolic",
8381   /* label, accelerator */       N_("Cu_t"), "<control>X",
8382   /* tooltip */                  N_("Prepare the selected files to be moved with a Paste command"),
8383 				 G_CALLBACK (action_cut_files_callback) },
8384   /* name, stock id */         { "Copy", "edit-copy-symbolic",
8385   /* label, accelerator */       N_("_Copy"), "<control>C",
8386   /* tooltip */                  N_("Prepare the selected files to be copied with a Paste command"),
8387 				 G_CALLBACK (action_copy_files_callback) },
8388   /* name, stock id */         { "Paste", "edit-paste-symbolic",
8389   /* label, accelerator */       N_("_Paste"), "<control>V",
8390   /* tooltip */                  N_("Move or copy files previously selected by a Cut or Copy command"),
8391 				 G_CALLBACK (action_paste_files_callback) },
8392   /* We make accelerator "" instead of null here to not inherit the stock
8393      accelerator for paste */
8394   /* name, stock id */         { "Paste Files Into", "edit-paste-symbolic",
8395   /* label, accelerator */       N_("_Paste Into Folder"), "",
8396   /* tooltip */                  N_("Move or copy files previously selected by a Cut or Copy command into the selected folder"),
8397 				 G_CALLBACK (action_paste_files_into_callback) },
8398   /* name, stock id, label */  { "CopyToMenu", NULL, N_("Cop_y to") },
8399   /* name, stock id, label */  { "MoveToMenu", NULL, N_("M_ove to") },
8400   /* name, stock id */         { "Select All", NULL,
8401   /* label, accelerator */       N_("Select _All"), "<control>A",
8402   /* tooltip */                  N_("Select all items in this window"),
8403 				 G_CALLBACK (action_select_all_callback) },
8404   /* name, stock id */         { "Select Pattern", NULL,
8405   /* label, accelerator */       N_("Select I_tems Matching..."), "<control>S",
8406   /* tooltip */                  N_("Select items in this window matching a given pattern"),
8407 				 G_CALLBACK (action_select_pattern_callback) },
8408   /* name, stock id */         { "Invert Selection", NULL,
8409   /* label, accelerator */       N_("_Invert Selection"), "<control><shift>I",
8410   /* tooltip */                  N_("Select all and only the items that are not currently selected"),
8411 				 G_CALLBACK (action_invert_selection_callback) },
8412   /* name, stock id */         { "Duplicate", NULL,
8413   /* label, accelerator */       N_("D_uplicate"), NULL,
8414   /* tooltip */                  N_("Duplicate each selected item"),
8415 				 G_CALLBACK (action_duplicate_callback) },
8416   /* name, stock id */         { "Create Link", NULL,
8417   /* label, accelerator */       N_("Ma_ke Link"), "<control>M",
8418   /* tooltip */                  N_("Create a symbolic link for each selected item"),
8419 				 G_CALLBACK (action_create_link_callback) },
8420   /* name, stock id */         { "Rename", NULL,
8421   /* label, accelerator */       N_("_Rename..."), "F2",
8422   /* tooltip */                  N_("Rename selected item"),
8423 				 G_CALLBACK (action_rename_callback) },
8424   /* name, stock id */         { "RenameSelectAll", NULL,
8425   /* label, accelerator */       "RenameSelectAll", "<shift>F2",
8426   /* tooltip */                  NULL,
8427 				 G_CALLBACK (action_rename_select_all_callback) },
8428   /* name, stock id */         { "Trash", NULL,
8429   /* label, accelerator */       N_("Mo_ve to Trash"), NULL,
8430   /* tooltip */                  N_("Move each selected item to the Trash"),
8431 				 G_CALLBACK (action_trash_callback) },
8432   /* name, stock id */         { "Delete", NULL,
8433   /* label, accelerator */       N_("_Delete"), NULL,
8434   /* tooltip */                  N_("Delete each selected item, without moving to the Trash"),
8435 				 G_CALLBACK (action_delete_callback) },
8436   /* name, stock id */         { "Restore From Trash", NULL,
8437   /* label, accelerator */       N_("_Restore"), NULL,
8438 				 NULL,
8439                  G_CALLBACK (action_restore_from_trash_callback) },
8440  /* name, stock id */          { "Undo", "edit-undo-symbolic",
8441  /* label, accelerator */        N_("_Undo"), "<control>Z",
8442  /* tooltip */                   N_("Undo the last action"),
8443                                  G_CALLBACK (action_undo_callback) },
8444  /* name, stock id */	       { "Redo", "edit-redo-symbolic",
8445  /* label, accelerator */        N_("_Redo"), "<control>Y",
8446  /* tooltip */                   N_("Redo the last undone action"),
8447                                  G_CALLBACK (action_redo_callback) },
8448   /*
8449    * multiview-TODO: decide whether "Reset to Defaults" should
8450    * be window-wide, and not just view-wide.
8451    * Since this also resets the "Show hidden files" mode,
8452    * it is a mixture of both ATM.
8453    */
8454   /* name, stock id */         { "Reset to Defaults", NULL,
8455   /* label, accelerator */       N_("Reset View to _Defaults"), NULL,
8456   /* tooltip */                  N_("Reset sorting order and zoom level to match preferences for this view"),
8457 				 G_CALLBACK (action_reset_to_defaults_callback) },
8458   /* name, stock id */         { "Connect To Server Link", NULL,
8459   /* label, accelerator */       N_("Connect To This Server"), NULL,
8460   /* tooltip */                  N_("Make a permanent connection to this server"),
8461 				 G_CALLBACK (action_connect_to_server_link_callback) },
8462   /* name, stock id */         { "Mount Volume", "media-mount-symbolic",
8463   /* label, accelerator */       N_("_Mount"), NULL,
8464   /* tooltip */                  N_("Mount the selected volume"),
8465 				 G_CALLBACK (action_mount_volume_callback) },
8466   /* name, stock id */         { "Unmount Volume", "media-eject-symbolic",
8467   /* label, accelerator */       N_("_Unmount"), NULL,
8468   /* tooltip */                  N_("Unmount the selected volume"),
8469 				 G_CALLBACK (action_unmount_volume_callback) },
8470   /* name, stock id */         { "Eject Volume", "media-eject-symbolic",
8471   /* label, accelerator */       N_("_Eject"), NULL,
8472   /* tooltip */                  N_("Eject the selected volume"),
8473 				 G_CALLBACK (action_eject_volume_callback) },
8474   /* name, stock id */         { "Start Volume", NULL,
8475   /* label, accelerator */       N_("_Start"), NULL,
8476   /* tooltip */                  N_("Start the selected volume"),
8477 				 G_CALLBACK (action_start_volume_callback) },
8478   /* name, stock id */         { "Stop Volume", NULL,
8479   /* label, accelerator */       N_("_Stop"), NULL,
8480   /* tooltip */                  N_("Stop the selected volume"),
8481 				 G_CALLBACK (action_stop_volume_callback) },
8482   /* name, stock id */         { "Poll", NULL,
8483   /* label, accelerator */       N_("_Detect Media"), NULL,
8484   /* tooltip */                  N_("Detect media in the selected drive"),
8485 				 G_CALLBACK (action_detect_media_callback) },
8486   /* name, stock id */         { "Self Mount Volume", "media-mount-symbolic",
8487   /* label, accelerator */       N_("_Mount"), NULL,
8488   /* tooltip */                  N_("Mount the volume associated with the open folder"),
8489 				 G_CALLBACK (action_self_mount_volume_callback) },
8490   /* name, stock id */         { "Self Unmount Volume", "media-eject-symbolic",
8491   /* label, accelerator */       N_("_Unmount"), NULL,
8492   /* tooltip */                  N_("Unmount the volume associated with the open folder"),
8493 				 G_CALLBACK (action_self_unmount_volume_callback) },
8494   /* name, stock id */         { "Self Eject Volume", "media-eject-symbolic",
8495   /* label, accelerator */       N_("_Eject"), NULL,
8496   /* tooltip */                  N_("Eject the volume associated with the open folder"),
8497 				 G_CALLBACK (action_self_eject_volume_callback) },
8498   /* name, stock id */         { "Self Start Volume", NULL,
8499   /* label, accelerator */       N_("_Start"), NULL,
8500   /* tooltip */                  N_("Start the volume associated with the open folder"),
8501 				 G_CALLBACK (action_self_start_volume_callback) },
8502   /* name, stock id */         { "Self Stop Volume", NULL,
8503   /* label, accelerator */       N_("_Stop"), NULL,
8504   /* tooltip */                  N_("Stop the volume associated with the open folder"),
8505 				 G_CALLBACK (action_self_stop_volume_callback) },
8506   /* name, stock id */         { "Self Poll", NULL,
8507   /* label, accelerator */       N_("_Detect Media"), NULL,
8508   /* tooltip */                  N_("Detect media in the selected drive"),
8509 				 G_CALLBACK (action_self_detect_media_callback) },
8510   /* name, stock id */         { "OpenCloseParent", NULL,
8511   /* label, accelerator */       N_("Open File and Close window"), "<alt><shift>Down",
8512   /* tooltip */                  NULL,
8513 				 G_CALLBACK (action_open_close_parent_callback) },
8514   /* name, stock id */         { "Save Search", NULL,
8515   /* label, accelerator */       N_("Sa_ve Search"), NULL,
8516   /* tooltip */                  N_("Save the edited search"),
8517 				 G_CALLBACK (action_save_search_callback) },
8518   /* name, stock id */         { "Save Search As", NULL,
8519   /* label, accelerator */       N_("Sa_ve Search As..."), NULL,
8520   /* tooltip */                  N_("Save the current search as a file"),
8521 				 G_CALLBACK (action_save_search_as_callback) },
8522 
8523   /* Location-specific actions */
8524   /* name, stock id */         { NEMO_ACTION_LOCATION_OPEN_ALTERNATE, NULL,
8525   /* label, accelerator */       N_("Open in Navigation Window"), "",
8526   /* tooltip */                  N_("Open this folder in a navigation window"),
8527 				 G_CALLBACK (action_location_open_alternate_callback) },
8528   /* name, stock id */         { NEMO_ACTION_LOCATION_OPEN_IN_NEW_TAB, NULL,
8529   /* label, accelerator */       N_("Open in New _Tab"), "",
8530   /* tooltip */                  N_("Open this folder in a new tab"),
8531 				 G_CALLBACK (action_location_open_in_new_tab_callback) },
8532 
8533   /* name, stock id */         { NEMO_ACTION_LOCATION_CUT, "edit-cut-symbolic",
8534   /* label, accelerator */       N_("Cu_t"), "",
8535   /* tooltip */                  N_("Prepare this folder to be moved with a Paste command"),
8536 				 G_CALLBACK (action_location_cut_callback) },
8537   /* name, stock id */         { NEMO_ACTION_LOCATION_COPY, "edit-copy-symbolic",
8538   /* label, accelerator */       N_("_Copy"), "",
8539   /* tooltip */                  N_("Prepare this folder to be copied with a Paste command"),
8540 				 G_CALLBACK (action_location_copy_callback) },
8541   /* name, stock id */         { NEMO_ACTION_LOCATION_PASTE_FILES_INTO, "edit-paste-symbolic",
8542   /* label, accelerator */       N_("_Paste Into Folder"), "",
8543   /* tooltip */                  N_("Move or copy files previously selected by a Cut or Copy command into this folder"),
8544 				 G_CALLBACK (action_location_paste_files_into_callback) },
8545 
8546   /* name, stock id */         { NEMO_ACTION_LOCATION_TRASH, NULL,
8547   /* label, accelerator */       N_("Mo_ve to Trash"), "",
8548   /* tooltip */                  N_("Move this folder to the Trash"),
8549 				 G_CALLBACK (action_location_trash_callback) },
8550   /* name, stock id */         { NEMO_ACTION_LOCATION_DELETE, NEMO_ICON_DELETE,
8551   /* label, accelerator */       N_("_Delete"), "",
8552   /* tooltip */                  N_("Delete this folder, without moving to the Trash"),
8553 				 G_CALLBACK (action_location_delete_callback) },
8554   /* name, stock id */         { NEMO_ACTION_LOCATION_RESTORE_FROM_TRASH, NULL,
8555   /* label, accelerator */       N_("_Restore"), NULL, NULL,
8556 				 G_CALLBACK (action_location_restore_from_trash_callback) },
8557 
8558   /* name, stock id */         { "Location Mount Volume", "media-mount-symbolic",
8559   /* label, accelerator */       N_("_Mount"), NULL,
8560   /* tooltip */                  N_("Mount the volume associated with this folder"),
8561 				 G_CALLBACK (action_location_mount_volume_callback) },
8562   /* name, stock id */         { "Location Unmount Volume", "media-eject-symbolic",
8563   /* label, accelerator */       N_("_Unmount"), NULL,
8564   /* tooltip */                  N_("Unmount the volume associated with this folder"),
8565 				 G_CALLBACK (action_location_unmount_volume_callback) },
8566   /* name, stock id */         { "Location Eject Volume", "media-eject-symbolic",
8567   /* label, accelerator */       N_("_Eject"), NULL,
8568   /* tooltip */                  N_("Eject the volume associated with this folder"),
8569 				 G_CALLBACK (action_location_eject_volume_callback) },
8570   /* name, stock id */         { "Location Start Volume", NULL,
8571   /* label, accelerator */       N_("_Start"), NULL,
8572   /* tooltip */                  N_("Start the volume associated with this folder"),
8573 				 G_CALLBACK (action_location_start_volume_callback) },
8574   /* name, stock id */         { "Location Stop Volume", NULL,
8575   /* label, accelerator */       N_("_Stop"), NULL,
8576   /* tooltip */                  N_("Stop the volume associated with this folder"),
8577 				 G_CALLBACK (action_location_stop_volume_callback) },
8578   /* name, stock id */         { "Location Poll", NULL,
8579   /* label, accelerator */       N_("_Detect Media"), NULL,
8580   /* tooltip */                  N_("Detect media in the selected drive"),
8581 				 G_CALLBACK (action_location_detect_media_callback) },
8582 
8583   /* name, stock id */         { "LocationProperties", "document-properties-symbolic",
8584   /* label, accelerator */       N_("_Properties"), NULL,
8585   /* tooltip */                  N_("View or modify the properties of this folder"),
8586 				 G_CALLBACK (action_location_properties_callback) },
8587 
8588   /* name, stock id, label */  {NEMO_ACTION_COPY_TO_NEXT_PANE, NULL, N_("_Other pane"),
8589 				NULL, N_("Copy the current selection to the other pane in the window"),
8590 				G_CALLBACK (action_copy_to_next_pane_callback) },
8591   /* name, stock id, label */  {NEMO_ACTION_MOVE_TO_NEXT_PANE, NULL, N_("_Other pane"),
8592 				NULL, N_("Move the current selection to the other pane in the window"),
8593 				G_CALLBACK (action_move_to_next_pane_callback) },
8594   /* name, stock id, label */  {NEMO_ACTION_COPY_TO_HOME, NULL,
8595 				N_("_Home"), NULL,
8596 				N_("Copy the current selection to the home folder"),
8597 				G_CALLBACK (action_copy_to_home_callback) },
8598   /* name, stock id, label */  {NEMO_ACTION_MOVE_TO_HOME, NULL,
8599 				N_("_Home"), NULL,
8600 				N_("Move the current selection to the home folder"),
8601 				G_CALLBACK (action_move_to_home_callback) },
8602   /* name, stock id, label */  {NEMO_ACTION_COPY_TO_DESKTOP, NULL,
8603 				N_("_Desktop"), NULL,
8604 				N_("Copy the current selection to the desktop"),
8605 				G_CALLBACK (action_copy_to_desktop_callback) },
8606   /* name, stock id, label */  {NEMO_ACTION_MOVE_TO_DESKTOP, NULL,
8607 				N_("_Desktop"), NULL,
8608 				N_("Move the current selection to the desktop"),
8609 				G_CALLBACK (action_move_to_desktop_callback) },
8610                                {NEMO_ACTION_BROWSE_MOVE_TO, "document-open-symbolic",
8611                 N_("Browse..."), NULL,
8612                 N_("Browse for a folder to move the selection to"),
8613                 G_CALLBACK (action_browse_for_move_to_folder_callback) },
8614                                {NEMO_ACTION_BROWSE_COPY_TO, "document-open-symbolic",
8615                 N_("Browse..."), NULL,
8616                 N_("Browse for a folder to copy the selection to"),
8617                 G_CALLBACK (action_browse_for_copy_to_folder_callback) },
8618                                {NEMO_ACTION_PIN_FILE, "xapp-pin-symbolic",
8619                 N_("P_in"), "<control><shift>D",
8620                 N_("Pin the selected file so it always appears at the top of this location's file list"),
8621                 G_CALLBACK (action_pin_unpin_file_callback) },
8622                                {NEMO_ACTION_UNPIN_FILE, "xapp-unpin-symbolic",
8623                 N_("Unp_in"), "<control><shift>D",
8624                 N_("Unpin the selected file from the top of this location's file list"),
8625                 G_CALLBACK (action_pin_unpin_file_callback) },
8626                                {NEMO_ACTION_FAVORITE_FILE, "xapp-favorite-symbolic",
8627                 N_("Add to favorites"), NULL,
8628                 N_("Add the selected file to your favorites"),
8629                 G_CALLBACK (action_favorite_unfavorite_file_callback) },
8630                                {NEMO_ACTION_UNFAVORITE_FILE, "xapp-unfavorite-symbolic",
8631                 N_("Remove from favorites"), NULL,
8632                 N_("Remove the selected file from your favorites"),
8633                 G_CALLBACK (action_favorite_unfavorite_file_callback) }
8634 };
8635 
8636 static void
connect_proxy(NemoView * view,GtkAction * action,GtkWidget * proxy,GtkActionGroup * action_group)8637 connect_proxy (NemoView *view,
8638                GtkAction *action,
8639                GtkWidget *proxy,
8640                GtkActionGroup *action_group)
8641 {
8642     if (strcmp (gtk_action_get_name (action), NEMO_ACTION_NEW_EMPTY_DOCUMENT) == 0 &&
8643         GTK_IS_IMAGE_MENU_ITEM (proxy)) {
8644 
8645         GtkWidget *image;
8646 
8647         image = gtk_image_new_from_icon_name ("text-x-generic", GTK_ICON_SIZE_MENU);
8648         gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (proxy), image);
8649         gtk_action_set_always_show_image (action, TRUE);
8650     }
8651 }
8652 
8653 static void
pre_activate(NemoView * view,GtkAction * action,GtkActionGroup * action_group)8654 pre_activate (NemoView *view,
8655 	      GtkAction *action,
8656 	      GtkActionGroup *action_group)
8657 {
8658 	GdkEvent *event;
8659 	GtkWidget *proxy;
8660 	gboolean activated_from_popup;
8661 
8662 	/* check whether action was activated through a popup menu.
8663 	 * If not, unset the last stored context menu popup position */
8664 	activated_from_popup = FALSE;
8665 
8666 	event = gtk_get_current_event ();
8667 	proxy = gtk_get_event_widget (event);
8668 
8669 	if (proxy != NULL) {
8670 		GtkWidget *toplevel;
8671 		GdkWindowTypeHint hint;
8672 
8673 		toplevel = gtk_widget_get_toplevel (proxy);
8674 
8675 		if (GTK_IS_WINDOW (toplevel)) {
8676 			hint = gtk_window_get_type_hint (GTK_WINDOW (toplevel));
8677 
8678 			if (hint == GDK_WINDOW_TYPE_HINT_POPUP_MENU) {
8679 				activated_from_popup = TRUE;
8680 			}
8681 		}
8682 	}
8683 
8684 	if (!activated_from_popup) {
8685 		update_context_menu_position_from_event (view, NULL);
8686 	}
8687 }
8688 
8689 static void
real_merge_menus(NemoView * view)8690 real_merge_menus (NemoView *view)
8691 {
8692 	GtkActionGroup *action_group;
8693 	GtkUIManager *ui_manager;
8694 	GtkAction *action;
8695 	char *tooltip;
8696 
8697 	ui_manager = nemo_window_get_ui_manager (view->details->window);
8698 
8699 	action_group = gtk_action_group_new ("DirViewActions");
8700 	gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
8701 	view->details->dir_action_group = action_group;
8702 
8703 	gtk_action_group_add_actions (action_group,
8704 				      directory_view_entries, G_N_ELEMENTS (directory_view_entries),
8705 				      view);
8706 
8707 	tooltip = g_strdup_printf (_("Run scripts"));
8708 	/* Create a script action here specially because its tooltip is dynamic */
8709 	action = gtk_action_new ("Scripts", _("_Scripts"), tooltip, NULL);
8710 	gtk_action_group_add_action (action_group, action);
8711 	g_object_unref (action);
8712 	g_free (tooltip);
8713 
8714 	action = gtk_action_group_get_action (action_group, NEMO_ACTION_NO_TEMPLATES);
8715 	gtk_action_set_sensitive (action, FALSE);
8716 
8717 	g_signal_connect_object (action_group, "connect-proxy",
8718 				 G_CALLBACK (connect_proxy), G_OBJECT (view),
8719 				 G_CONNECT_SWAPPED);
8720 	g_signal_connect_object (action_group, "pre-activate",
8721 				 G_CALLBACK (pre_activate), G_OBJECT (view),
8722 				 G_CONNECT_SWAPPED);
8723 
8724 	/* Insert action group at end so clipboard action group ends up before it */
8725 	gtk_ui_manager_insert_action_group (ui_manager, action_group, -1);
8726 	g_object_unref (action_group); /* owned by ui manager */
8727 
8728     view->details->dir_merge_id = gtk_ui_manager_add_ui_from_resource (ui_manager, "/org/nemo/nemo-directory-view-ui.xml", NULL);
8729 
8730 	view->details->scripts_invalid = TRUE;
8731 	view->details->templates_invalid = TRUE;
8732     view->details->actions_invalid = TRUE;
8733 }
8734 
8735 static gboolean
can_paste_into_file(NemoFile * file)8736 can_paste_into_file (NemoFile *file)
8737 {
8738 	if (nemo_file_is_directory (file) &&
8739 	    nemo_file_can_write (file)) {
8740 		return TRUE;
8741 	}
8742 	if (nemo_file_has_activation_uri (file)) {
8743 		GFile *location;
8744 		NemoFile *activation_file;
8745 		gboolean res;
8746 
8747 		location = nemo_file_get_activation_location (file);
8748 		activation_file = nemo_file_get (location);
8749 		g_object_unref (location);
8750 
8751 		/* The target location might not have data for it read yet,
8752 		   and we can't want to do sync I/O, so treat the unknown
8753 		   case as can-write */
8754 		res = (nemo_file_get_file_type (activation_file) == G_FILE_TYPE_UNKNOWN) ||
8755 			(nemo_file_get_file_type (activation_file) == G_FILE_TYPE_DIRECTORY &&
8756 			 nemo_file_can_write (activation_file));
8757 
8758 		nemo_file_unref (activation_file);
8759 
8760 		return res;
8761 	}
8762 
8763 	return FALSE;
8764 }
8765 
8766 static void
clipboard_targets_received(GtkClipboard * clipboard,GdkAtom * targets,int n_targets,gpointer user_data)8767 clipboard_targets_received (GtkClipboard     *clipboard,
8768                             GdkAtom          *targets,
8769                             int               n_targets,
8770 			    gpointer          user_data)
8771 {
8772 	NemoView *view;
8773 	gboolean can_paste;
8774 	int i;
8775 	GList *selection;
8776 	int count;
8777 	GtkAction *action;
8778 
8779 	view = NEMO_VIEW (user_data);
8780 	can_paste = FALSE;
8781 
8782 	if (view->details->window == NULL ||
8783 	    !view->details->active) {
8784 		/* We've been destroyed or became inactive since call */
8785 		g_object_unref (view);
8786 		return;
8787 	}
8788 
8789 	if (targets) {
8790 		for (i=0; i < n_targets; i++) {
8791 			if (targets[i] == copied_files_atom) {
8792 				can_paste = TRUE;
8793 			}
8794 		}
8795 	}
8796 
8797 
8798 	selection = nemo_view_get_selection (view);
8799 	count = g_list_length (selection);
8800 
8801 	action = gtk_action_group_get_action (view->details->dir_action_group,
8802 					      NEMO_ACTION_PASTE);
8803 	gtk_action_set_sensitive (action,
8804 				  can_paste && !nemo_view_is_read_only (view));
8805 
8806 	action = gtk_action_group_get_action (view->details->dir_action_group,
8807 					      NEMO_ACTION_PASTE_FILES_INTO);
8808 	gtk_action_set_sensitive (action,
8809 	                          can_paste && count == 1 &&
8810 	                          can_paste_into_file (NEMO_FILE (selection->data)));
8811 
8812 	action = gtk_action_group_get_action (view->details->dir_action_group,
8813 					      NEMO_ACTION_LOCATION_PASTE_FILES_INTO);
8814 	g_object_set_data (G_OBJECT (action),
8815 			   "can-paste-according-to-clipboard",
8816 			   GINT_TO_POINTER (can_paste));
8817 	gtk_action_set_sensitive (action,
8818 				  GPOINTER_TO_INT (g_object_get_data (G_OBJECT (action),
8819 								      "can-paste-according-to-clipboard")) &&
8820 				  GPOINTER_TO_INT (g_object_get_data (G_OBJECT (action),
8821 								      "can-paste-according-to-destination")));
8822 
8823 	nemo_file_list_free (selection);
8824 
8825 	g_object_unref (view);
8826 }
8827 
8828 static gboolean
should_show_empty_trash(NemoView * view)8829 should_show_empty_trash (NemoView *view)
8830 {
8831 	return (showing_trash_directory (view));
8832 }
8833 
8834 static gboolean
file_list_all_are_folders(GList * file_list)8835 file_list_all_are_folders (GList *file_list)
8836 {
8837 	GList *l;
8838 	NemoFile *file, *linked_file;
8839 	char *activation_uri;
8840 	gboolean is_dir;
8841 
8842 	for (l = file_list; l != NULL; l = l->next) {
8843 		file = NEMO_FILE (l->data);
8844 		if (nemo_file_is_nemo_link (file) &&
8845 		    !NEMO_IS_DESKTOP_ICON_FILE (file)) {
8846 			if (nemo_file_is_launcher (file)) {
8847 				return FALSE;
8848 			}
8849 
8850 			activation_uri = nemo_file_get_activation_uri (file);
8851 
8852 			if (activation_uri == NULL) {
8853 				g_free (activation_uri);
8854 				return FALSE;
8855 			}
8856 
8857 			linked_file = nemo_file_get_existing_by_uri (activation_uri);
8858 
8859 			/* We might not actually know the type of the linked file yet,
8860 			 * however we don't want to schedule a read, since that might do things
8861 			 * like ask for password etc. This is a bit unfortunate, but I don't
8862 			 * know any way around it, so we do various heuristics here
8863 			 * to get things mostly right
8864 			 */
8865 			is_dir =
8866 				(linked_file != NULL &&
8867 				 nemo_file_is_directory (linked_file)) ||
8868 				(activation_uri != NULL &&
8869 				 activation_uri[strlen (activation_uri) - 1] == '/');
8870 
8871 			nemo_file_unref (linked_file);
8872 			g_free (activation_uri);
8873 
8874 			if (!is_dir) {
8875 				return FALSE;
8876 			}
8877 		} else if (!(nemo_file_is_directory (file) ||
8878 			     NEMO_IS_DESKTOP_ICON_FILE (file))) {
8879 			return FALSE;
8880 		}
8881 	}
8882 	return TRUE;
8883 }
8884 
8885 static void
file_should_show_foreach(NemoFile * file,gboolean * show_mount,gboolean * show_unmount,gboolean * show_eject,gboolean * show_connect,gboolean * show_start,gboolean * show_stop,gboolean * show_poll,GDriveStartStopType * start_stop_type)8886 file_should_show_foreach (NemoFile        *file,
8887 			  gboolean            *show_mount,
8888 			  gboolean            *show_unmount,
8889 			  gboolean            *show_eject,
8890 			  gboolean            *show_connect,
8891 			  gboolean            *show_start,
8892 			  gboolean            *show_stop,
8893 			  gboolean            *show_poll,
8894 			  GDriveStartStopType *start_stop_type)
8895 {
8896 	char *uri;
8897 
8898 	*show_mount = FALSE;
8899 	*show_unmount = FALSE;
8900 	*show_eject = FALSE;
8901 	*show_connect = FALSE;
8902 	*show_start = FALSE;
8903 	*show_stop = FALSE;
8904 	*show_poll = FALSE;
8905 
8906 	if (nemo_file_can_eject (file)) {
8907 		*show_eject = TRUE;
8908 	}
8909 
8910 	if (nemo_file_can_mount (file)) {
8911 		*show_mount = TRUE;
8912 	}
8913 
8914 	if (nemo_file_can_start (file) || nemo_file_can_start_degraded (file)) {
8915 		*show_start = TRUE;
8916 	}
8917 
8918 	if (nemo_file_can_stop (file)) {
8919 		*show_stop = TRUE;
8920 	}
8921 
8922 	/* Dot not show both Unmount and Eject/Safe Removal; too confusing to
8923 	 * have too many menu entries */
8924 	if (nemo_file_can_unmount (file) && !*show_eject && !*show_stop) {
8925 		*show_unmount = TRUE;
8926 	}
8927 
8928 	if (nemo_file_can_poll_for_media (file) && !nemo_file_is_media_check_automatic (file)) {
8929 		*show_poll = TRUE;
8930 	}
8931 
8932 	*start_stop_type = nemo_file_get_start_stop_type (file);
8933 
8934 	if (nemo_file_is_nemo_link (file)) {
8935 		uri = nemo_file_get_activation_uri (file);
8936 		if (uri != NULL &&
8937 		    (g_str_has_prefix (uri, "ftp:") ||
8938 		     g_str_has_prefix (uri, "ssh:") ||
8939 		     g_str_has_prefix (uri, "sftp:") ||
8940 		     g_str_has_prefix (uri, "dav:") ||
8941 		     g_str_has_prefix (uri, "davs:"))) {
8942 			*show_connect = TRUE;
8943 		}
8944 		g_free (uri);
8945 	}
8946 }
8947 
8948 static void
file_should_show_self(NemoFile * file,gboolean * show_mount,gboolean * show_unmount,gboolean * show_eject,gboolean * show_start,gboolean * show_stop,gboolean * show_poll,GDriveStartStopType * start_stop_type)8949 file_should_show_self (NemoFile        *file,
8950 		       gboolean            *show_mount,
8951 		       gboolean            *show_unmount,
8952 		       gboolean            *show_eject,
8953 		       gboolean            *show_start,
8954 		       gboolean            *show_stop,
8955 		       gboolean            *show_poll,
8956 		       GDriveStartStopType *start_stop_type)
8957 {
8958 	*show_mount = FALSE;
8959 	*show_unmount = FALSE;
8960 	*show_eject = FALSE;
8961 	*show_start = FALSE;
8962 	*show_stop = FALSE;
8963 	*show_poll = FALSE;
8964 
8965 	if (file == NULL) {
8966 		return;
8967 	}
8968 
8969 	if (nemo_file_can_eject (file)) {
8970 		*show_eject = TRUE;
8971 	}
8972 
8973 	if (nemo_file_can_mount (file)) {
8974 		*show_mount = TRUE;
8975 	}
8976 
8977 	if (nemo_file_can_start (file) || nemo_file_can_start_degraded (file)) {
8978 		*show_start = TRUE;
8979 	}
8980 
8981 	if (nemo_file_can_stop (file)) {
8982 		*show_stop = TRUE;
8983 	}
8984 
8985 	/* Dot not show both Unmount and Eject/Safe Removal; too confusing to
8986 	 * have too many menu entries */
8987 	if (nemo_file_can_unmount (file) && !*show_eject && !*show_stop) {
8988 		*show_unmount = TRUE;
8989 	}
8990 
8991 	if (nemo_file_can_poll_for_media (file) && !nemo_file_is_media_check_automatic (file)) {
8992 		*show_poll = TRUE;
8993 	}
8994 
8995 	*start_stop_type = nemo_file_get_start_stop_type (file);
8996 
8997 }
8998 
8999 static gboolean
files_are_all_directories(GList * files)9000 files_are_all_directories (GList *files)
9001 {
9002 	NemoFile *file;
9003 	GList *l;
9004 	gboolean all_directories;
9005 
9006 	all_directories = TRUE;
9007 
9008 	for (l = files; l != NULL; l = l->next) {
9009 		file = NEMO_FILE (l->data);
9010 		all_directories &= nemo_file_is_directory (file);
9011 	}
9012 
9013 	return all_directories;
9014 }
9015 
9016 static gboolean
files_is_none_directory(GList * files)9017 files_is_none_directory (GList *files)
9018 {
9019 	NemoFile *file;
9020 	GList *l;
9021 	gboolean no_directory;
9022 
9023 	no_directory = TRUE;
9024 
9025 	for (l = files; l != NULL; l = l->next) {
9026 		file = NEMO_FILE (l->data);
9027 		no_directory &= !nemo_file_is_directory (file);
9028 	}
9029 
9030 	return no_directory;
9031 }
9032 
9033 static void
update_restore_from_trash_action(GtkAction * action,GList * files,gboolean is_self)9034 update_restore_from_trash_action (GtkAction *action,
9035 				  GList *files,
9036 				  gboolean is_self)
9037 {
9038 	NemoFile *original_file;
9039 	NemoFile *original_dir;
9040 	GHashTable *original_dirs_hash;
9041 	GList *original_dirs;
9042 	GFile *original_location;
9043 	char *tooltip, *original_name;
9044 
9045 	original_file = NULL;
9046 	original_dir = NULL;
9047 	original_dirs = NULL;
9048 	original_dirs_hash = NULL;
9049 	original_location = NULL;
9050 	original_name = NULL;
9051 
9052 	if (files != NULL) {
9053 		if (g_list_length (files) == 1) {
9054 			original_file = nemo_file_get_trash_original_file (files->data);
9055 		} else {
9056 			original_dirs_hash = nemo_trashed_files_get_original_directories (files, NULL);
9057 			if (original_dirs_hash != NULL) {
9058 				original_dirs = g_hash_table_get_keys (original_dirs_hash);
9059 				if (g_list_length (original_dirs) == 1) {
9060 					original_dir = nemo_file_ref (NEMO_FILE (original_dirs->data));
9061 				}
9062 			}
9063 		}
9064 	}
9065 
9066 	if (original_file != NULL || original_dirs != NULL) {
9067 		gtk_action_set_visible (action, TRUE);
9068 
9069 		if (original_file != NULL) {
9070 			original_location = nemo_file_get_location (original_file);
9071 		} else if (original_dir != NULL) {
9072 			original_location = nemo_file_get_location (original_dir);
9073 		}
9074 
9075 		if (original_location != NULL) {
9076 			original_name = g_file_get_parse_name (original_location);
9077 		}
9078 
9079 		if (is_self) {
9080 			g_assert (g_list_length (files) == 1);
9081 			g_assert (original_location != NULL);
9082 			tooltip = g_strdup_printf (_("Move the open folder out of the trash to \"%s\""), original_name);
9083 		} else if (files_are_all_directories (files)) {
9084 			if (original_name != NULL) {
9085 				tooltip = g_strdup_printf (ngettext ("Move the selected folder out of the trash to \"%s\"",
9086 								     "Move the selected folders out of the trash to \"%s\"",
9087 								     g_list_length (files)), original_name);
9088 			} else {
9089 				tooltip = g_strdup_printf (ngettext ("Move the selected folder out of the trash",
9090 								     "Move the selected folders out of the trash",
9091 								     g_list_length (files)));
9092 			}
9093 		} else if (files_is_none_directory (files)) {
9094 			if (original_name != NULL) {
9095 				tooltip = g_strdup_printf (ngettext ("Move the selected file out of the trash to \"%s\"",
9096 								     "Move the selected files out of the trash to \"%s\"",
9097 								     g_list_length (files)), original_name);
9098 			} else {
9099 				tooltip = g_strdup_printf (ngettext ("Move the selected file out of the trash",
9100 								     "Move the selected files out of the trash",
9101 								     g_list_length (files)));
9102 			}
9103 		} else {
9104 			if (original_name != NULL) {
9105 				tooltip = g_strdup_printf (ngettext ("Move the selected item out of the trash to \"%s\"",
9106 								     "Move the selected items out of the trash to \"%s\"",
9107 								     g_list_length (files)), original_name);
9108 			} else {
9109 				tooltip = g_strdup_printf (ngettext ("Move the selected item out of the trash",
9110 								     "Move the selected items out of the trash",
9111 								     g_list_length (files)));
9112 			}
9113 		}
9114 		g_free (original_name);
9115 
9116 		g_object_set (action, "tooltip", tooltip, NULL);
9117 		g_free (tooltip);
9118 
9119 		if (original_location != NULL) {
9120 			g_object_unref (original_location);
9121 		}
9122 	} else {
9123 		gtk_action_set_visible (action, FALSE);
9124 	}
9125 
9126 	nemo_file_unref (original_file);
9127 	nemo_file_unref (original_dir);
9128 	g_list_free (original_dirs);
9129 
9130 	if (original_dirs_hash != NULL) {
9131 		g_hash_table_destroy (original_dirs_hash);
9132 	}
9133 }
9134 
9135 static void
real_update_menus_volumes(NemoView * view,GList * selection,gint selection_count)9136 real_update_menus_volumes (NemoView *view,
9137 			   GList *selection,
9138 			   gint selection_count)
9139 {
9140 	GList *l;
9141 	NemoFile *file;
9142 	gboolean show_mount;
9143 	gboolean show_unmount;
9144 	gboolean show_eject;
9145 	gboolean show_connect;
9146 	gboolean show_start;
9147 	gboolean show_stop;
9148 	gboolean show_poll;
9149 	GDriveStartStopType start_stop_type;
9150 	gboolean show_self_mount;
9151 	gboolean show_self_unmount;
9152 	gboolean show_self_eject;
9153 	gboolean show_self_start;
9154 	gboolean show_self_stop;
9155 	gboolean show_self_poll;
9156 	GDriveStartStopType self_start_stop_type;
9157 	GtkAction *action;
9158 
9159 	show_mount = (selection != NULL);
9160 	show_unmount = (selection != NULL);
9161 	show_eject = (selection != NULL);
9162 	show_connect = (selection != NULL && selection_count == 1);
9163 	show_start = (selection != NULL && selection_count == 1);
9164 	show_stop = (selection != NULL && selection_count == 1);
9165 	show_poll = (selection != NULL && selection_count == 1);
9166 	start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN;
9167 	self_start_stop_type = G_DRIVE_START_STOP_TYPE_UNKNOWN;
9168 
9169 	for (l = selection; l != NULL && (show_mount || show_unmount
9170 					  || show_eject || show_connect
9171                                           || show_start || show_stop
9172 					  || show_poll);
9173 	     l = l->next) {
9174 		gboolean show_mount_one;
9175 		gboolean show_unmount_one;
9176 		gboolean show_eject_one;
9177 		gboolean show_connect_one;
9178 		gboolean show_start_one;
9179 		gboolean show_stop_one;
9180 		gboolean show_poll_one;
9181 
9182 		file = NEMO_FILE (l->data);
9183 		file_should_show_foreach (file,
9184 					  &show_mount_one,
9185 					  &show_unmount_one,
9186 					  &show_eject_one,
9187 					  &show_connect_one,
9188                                           &show_start_one,
9189                                           &show_stop_one,
9190 					  &show_poll_one,
9191 					  &start_stop_type);
9192 
9193 		show_mount &= show_mount_one;
9194 		show_unmount &= show_unmount_one;
9195 		show_eject &= show_eject_one;
9196 		show_connect &= show_connect_one;
9197 		show_start &= show_start_one;
9198 		show_stop &= show_stop_one;
9199 		show_poll &= show_poll_one;
9200 	}
9201 
9202 	action = gtk_action_group_get_action (view->details->dir_action_group,
9203 					      NEMO_ACTION_CONNECT_TO_SERVER_LINK);
9204 	gtk_action_set_visible (action, show_connect);
9205 
9206 	action = gtk_action_group_get_action (view->details->dir_action_group,
9207 					      NEMO_ACTION_MOUNT_VOLUME);
9208 	gtk_action_set_visible (action, show_mount);
9209 
9210 	action = gtk_action_group_get_action (view->details->dir_action_group,
9211 					      NEMO_ACTION_UNMOUNT_VOLUME);
9212 	gtk_action_set_visible (action, show_unmount);
9213 
9214 	action = gtk_action_group_get_action (view->details->dir_action_group,
9215 					      NEMO_ACTION_EJECT_VOLUME);
9216 	gtk_action_set_visible (action, show_eject);
9217 
9218 	action = gtk_action_group_get_action (view->details->dir_action_group,
9219 					      NEMO_ACTION_START_VOLUME);
9220 	gtk_action_set_visible (action, show_start);
9221 	if (show_start) {
9222 		switch (start_stop_type) {
9223 		default:
9224 		case G_DRIVE_START_STOP_TYPE_UNKNOWN:
9225 			gtk_action_set_label (action, _("_Start"));
9226 			gtk_action_set_tooltip (action, _("Start the selected drive"));
9227 			break;
9228 		case G_DRIVE_START_STOP_TYPE_SHUTDOWN:
9229 			gtk_action_set_label (action, _("_Start"));
9230 			gtk_action_set_tooltip (action, _("Start the selected drive"));
9231 			break;
9232 		case G_DRIVE_START_STOP_TYPE_NETWORK:
9233 			gtk_action_set_label (action, _("_Connect"));
9234 			gtk_action_set_tooltip (action, _("Connect to the selected drive"));
9235 			break;
9236 		case G_DRIVE_START_STOP_TYPE_MULTIDISK:
9237 			gtk_action_set_label (action, _("_Start Multi-disk Drive"));
9238 			gtk_action_set_tooltip (action, _("Start the selected multi-disk drive"));
9239 			break;
9240 		case G_DRIVE_START_STOP_TYPE_PASSWORD:
9241 			gtk_action_set_label (action, _("U_nlock Drive"));
9242 			gtk_action_set_tooltip (action, _("Unlock the selected drive"));
9243 			break;
9244 		}
9245 	}
9246 
9247 	action = gtk_action_group_get_action (view->details->dir_action_group,
9248 					      NEMO_ACTION_STOP_VOLUME);
9249 	gtk_action_set_visible (action, show_stop);
9250 	if (show_stop) {
9251 		switch (start_stop_type) {
9252 		default:
9253 		case G_DRIVE_START_STOP_TYPE_UNKNOWN:
9254 			gtk_action_set_label (action, _("_Stop"));
9255 			gtk_action_set_tooltip (action, _("Stop the selected drive"));
9256 			break;
9257 		case G_DRIVE_START_STOP_TYPE_SHUTDOWN:
9258 			gtk_action_set_label (action, _("_Safely Remove Drive"));
9259 			gtk_action_set_tooltip (action, _("Safely remove the selected drive"));
9260 			break;
9261 		case G_DRIVE_START_STOP_TYPE_NETWORK:
9262 			gtk_action_set_label (action, _("_Disconnect"));
9263 			gtk_action_set_tooltip (action, _("Disconnect the selected drive"));
9264 			break;
9265 		case G_DRIVE_START_STOP_TYPE_MULTIDISK:
9266 			gtk_action_set_label (action, _("_Stop Multi-disk Drive"));
9267 			gtk_action_set_tooltip (action, _("Stop the selected multi-disk drive"));
9268 			break;
9269 		case G_DRIVE_START_STOP_TYPE_PASSWORD:
9270 			gtk_action_set_label (action, _("_Lock Drive"));
9271 			gtk_action_set_tooltip (action, _("Lock the selected drive"));
9272 			break;
9273 		}
9274 	}
9275 
9276 	action = gtk_action_group_get_action (view->details->dir_action_group,
9277 					      NEMO_ACTION_POLL);
9278 	gtk_action_set_visible (action, show_poll);
9279 
9280 	show_self_mount = show_self_unmount = show_self_eject =
9281 		show_self_start = show_self_stop = show_self_poll = FALSE;
9282 
9283 	file = nemo_view_get_directory_as_file (view);
9284 	file_should_show_self (file,
9285 			       &show_self_mount,
9286 			       &show_self_unmount,
9287 			       &show_self_eject,
9288 			       &show_self_start,
9289 			       &show_self_stop,
9290 			       &show_self_poll,
9291 			       &self_start_stop_type);
9292 
9293 	action = gtk_action_group_get_action (view->details->dir_action_group,
9294 					      NEMO_ACTION_SELF_MOUNT_VOLUME);
9295 	gtk_action_set_visible (action, show_self_mount);
9296 
9297 	action = gtk_action_group_get_action (view->details->dir_action_group,
9298 					      NEMO_ACTION_SELF_UNMOUNT_VOLUME);
9299 	gtk_action_set_visible (action, show_self_unmount);
9300 
9301 	action = gtk_action_group_get_action (view->details->dir_action_group,
9302 					      NEMO_ACTION_SELF_EJECT_VOLUME);
9303 	gtk_action_set_visible (action, show_self_eject);
9304 
9305 	action = gtk_action_group_get_action (view->details->dir_action_group,
9306 					      NEMO_ACTION_SELF_START_VOLUME);
9307 	gtk_action_set_visible (action, show_self_start);
9308 	if (show_self_start) {
9309 		switch (self_start_stop_type) {
9310 		default:
9311 		case G_DRIVE_START_STOP_TYPE_UNKNOWN:
9312 			gtk_action_set_label (action, _("_Start"));
9313 			gtk_action_set_tooltip (action, _("Start the drive associated with the open folder"));
9314 			break;
9315 		case G_DRIVE_START_STOP_TYPE_SHUTDOWN:
9316 			gtk_action_set_label (action, _("_Start"));
9317 			gtk_action_set_tooltip (action, _("Start the drive associated with the open folder"));
9318 			break;
9319 		case G_DRIVE_START_STOP_TYPE_NETWORK:
9320 			gtk_action_set_label (action, _("_Connect"));
9321 			gtk_action_set_tooltip (action, _("Connect to the drive associated with the open folder"));
9322 			break;
9323 		case G_DRIVE_START_STOP_TYPE_MULTIDISK:
9324 			gtk_action_set_label (action, _("_Start Multi-disk Drive"));
9325 			gtk_action_set_tooltip (action, _("Start the multi-disk drive associated with the open folder"));
9326 			break;
9327 		case G_DRIVE_START_STOP_TYPE_PASSWORD:
9328 			gtk_action_set_label (action, _("_Unlock Drive"));
9329 			gtk_action_set_tooltip (action, _("Unlock the drive associated with the open folder"));
9330 			break;
9331 		}
9332 	}
9333 
9334 	action = gtk_action_group_get_action (view->details->dir_action_group,
9335 					      NEMO_ACTION_SELF_STOP_VOLUME);
9336 	gtk_action_set_visible (action, show_self_stop);
9337 	if (show_self_stop) {
9338 		switch (self_start_stop_type) {
9339 		default:
9340 		case G_DRIVE_START_STOP_TYPE_UNKNOWN:
9341 			gtk_action_set_label (action, _("_Stop"));
9342 			gtk_action_set_tooltip (action, _("_Stop the drive associated with the open folder"));
9343 			break;
9344 		case G_DRIVE_START_STOP_TYPE_SHUTDOWN:
9345 			gtk_action_set_label (action, _("_Safely Remove Drive"));
9346 			gtk_action_set_tooltip (action, _("Safely remove the drive associated with the open folder"));
9347 			break;
9348 		case G_DRIVE_START_STOP_TYPE_NETWORK:
9349 			gtk_action_set_label (action, _("_Disconnect"));
9350 			gtk_action_set_tooltip (action, _("Disconnect the drive associated with the open folder"));
9351 			break;
9352 		case G_DRIVE_START_STOP_TYPE_MULTIDISK:
9353 			gtk_action_set_label (action, _("_Stop Multi-disk Drive"));
9354 			gtk_action_set_tooltip (action, _("Stop the multi-disk drive associated with the open folder"));
9355 			break;
9356 		case G_DRIVE_START_STOP_TYPE_PASSWORD:
9357 			gtk_action_set_label (action, _("_Lock Drive"));
9358 			gtk_action_set_tooltip (action, _("Lock the drive associated with the open folder"));
9359 			break;
9360 		}
9361 	}
9362 
9363 	action = gtk_action_group_get_action (view->details->dir_action_group,
9364 					      NEMO_ACTION_SELF_POLL);
9365 	gtk_action_set_visible (action, show_self_poll);
9366 
9367 }
9368 
9369 static void
real_update_location_menu_volumes(NemoView * view)9370 real_update_location_menu_volumes (NemoView *view)
9371 {
9372 	GtkAction *action;
9373 	NemoFile *file;
9374 	gboolean show_mount;
9375 	gboolean show_unmount;
9376 	gboolean show_eject;
9377 	gboolean show_connect;
9378 	gboolean show_start;
9379 	gboolean show_stop;
9380 	gboolean show_poll;
9381 	GDriveStartStopType start_stop_type;
9382 
9383 	g_assert (NEMO_IS_VIEW (view));
9384 	g_assert (NEMO_IS_FILE (view->details->location_popup_directory_as_file));
9385 
9386 	file = NEMO_FILE (view->details->location_popup_directory_as_file);
9387 	file_should_show_foreach (file,
9388 				  &show_mount,
9389 				  &show_unmount,
9390 				  &show_eject,
9391 				  &show_connect,
9392 				  &show_start,
9393 				  &show_stop,
9394 				  &show_poll,
9395 				  &start_stop_type);
9396 
9397 	action = gtk_action_group_get_action (view->details->dir_action_group,
9398 					      NEMO_ACTION_LOCATION_MOUNT_VOLUME);
9399 	gtk_action_set_visible (action, show_mount);
9400 
9401 	action = gtk_action_group_get_action (view->details->dir_action_group,
9402 					      NEMO_ACTION_LOCATION_UNMOUNT_VOLUME);
9403 	gtk_action_set_visible (action, show_unmount);
9404 
9405 	action = gtk_action_group_get_action (view->details->dir_action_group,
9406 					      NEMO_ACTION_LOCATION_EJECT_VOLUME);
9407 	gtk_action_set_visible (action, show_eject);
9408 
9409 	action = gtk_action_group_get_action (view->details->dir_action_group,
9410 					      NEMO_ACTION_LOCATION_START_VOLUME);
9411 	gtk_action_set_visible (action, show_start);
9412 	if (show_start) {
9413 		switch (start_stop_type) {
9414 		default:
9415 		case G_DRIVE_START_STOP_TYPE_UNKNOWN:
9416 			gtk_action_set_label (action, _("_Start"));
9417 			gtk_action_set_tooltip (action, _("Start the selected drive"));
9418 			break;
9419 		case G_DRIVE_START_STOP_TYPE_SHUTDOWN:
9420 			gtk_action_set_label (action, _("_Start"));
9421 			gtk_action_set_tooltip (action, _("Start the selected drive"));
9422 			break;
9423 		case G_DRIVE_START_STOP_TYPE_NETWORK:
9424 			gtk_action_set_label (action, _("_Connect"));
9425 			gtk_action_set_tooltip (action, _("Connect to the selected drive"));
9426 			break;
9427 		case G_DRIVE_START_STOP_TYPE_MULTIDISK:
9428 			gtk_action_set_label (action, _("_Start Multi-disk Drive"));
9429 			gtk_action_set_tooltip (action, _("Start the selected multi-disk drive"));
9430 			break;
9431 		case G_DRIVE_START_STOP_TYPE_PASSWORD:
9432 			gtk_action_set_label (action, _("_Unlock Drive"));
9433 			gtk_action_set_tooltip (action, _("Unlock the selected drive"));
9434 			break;
9435 		}
9436 	}
9437 
9438 	action = gtk_action_group_get_action (view->details->dir_action_group,
9439 					      NEMO_ACTION_LOCATION_STOP_VOLUME);
9440 	gtk_action_set_visible (action, show_stop);
9441 	if (show_stop) {
9442 		switch (start_stop_type) {
9443 		default:
9444 		case G_DRIVE_START_STOP_TYPE_UNKNOWN:
9445 			gtk_action_set_label (action, _("_Stop"));
9446 			gtk_action_set_tooltip (action, _("Stop the selected volume"));
9447 			break;
9448 		case G_DRIVE_START_STOP_TYPE_SHUTDOWN:
9449 			gtk_action_set_label (action, _("_Safely Remove Drive"));
9450 			gtk_action_set_tooltip (action, _("Safely remove the selected drive"));
9451 			break;
9452 		case G_DRIVE_START_STOP_TYPE_NETWORK:
9453 			gtk_action_set_label (action, _("_Disconnect"));
9454 			gtk_action_set_tooltip (action, _("Disconnect the selected drive"));
9455 			break;
9456 		case G_DRIVE_START_STOP_TYPE_MULTIDISK:
9457 			gtk_action_set_label (action, _("_Stop Multi-disk Drive"));
9458 			gtk_action_set_tooltip (action, _("Stop the selected multi-disk drive"));
9459 			break;
9460 		case G_DRIVE_START_STOP_TYPE_PASSWORD:
9461 			gtk_action_set_label (action, _("_Lock Drive"));
9462 			gtk_action_set_tooltip (action, _("Lock the selected drive"));
9463 			break;
9464 		}
9465 	}
9466 
9467 	action = gtk_action_group_get_action (view->details->dir_action_group,
9468 					      NEMO_ACTION_LOCATION_POLL);
9469 	gtk_action_set_visible (action, show_poll);
9470 }
9471 
9472 /* TODO: we should split out this routine into two functions:
9473  * Update on clipboard changes
9474  * Update on selection changes
9475  */
9476 static void
real_update_paste_menu(NemoView * view,GList * selection,gint selection_count)9477 real_update_paste_menu (NemoView *view,
9478 			GList *selection,
9479 			gint selection_count)
9480 {
9481 	gboolean can_paste_files_into;
9482 	gboolean selection_is_read_only;
9483     gboolean selection_contains_recent;
9484     gboolean selection_contains_favorites;
9485 	gboolean is_read_only;
9486 	GtkAction *action;
9487 
9488 	selection_is_read_only = selection_count == 1 &&
9489 		(!nemo_file_can_write (NEMO_FILE (selection->data)) &&
9490 		 !nemo_file_has_activation_uri (NEMO_FILE (selection->data)));
9491 
9492 	is_read_only = nemo_view_is_read_only (view);
9493 
9494     selection_contains_recent = showing_recent_directory (view);
9495     selection_contains_favorites = showing_favorites_directory (view);
9496 
9497     can_paste_files_into = (!selection_contains_recent && !selection_contains_favorites &&
9498                             selection_count == 1 &&
9499                             can_paste_into_file (NEMO_FILE (selection->data)));
9500 
9501 	action = gtk_action_group_get_action (view->details->dir_action_group,
9502 					      NEMO_ACTION_PASTE);
9503 	gtk_action_set_sensitive (action, !is_read_only);
9504 
9505     gtk_action_set_visible (action, !selection_contains_recent && !selection_contains_favorites);
9506 
9507 	action = gtk_action_group_get_action (view->details->dir_action_group,
9508 					      NEMO_ACTION_PASTE_FILES_INTO);
9509 	gtk_action_set_visible (action, can_paste_files_into);
9510 	gtk_action_set_sensitive (action, !selection_is_read_only);
9511 
9512 	/* Ask the clipboard */
9513 	g_object_ref (view); /* Need to keep the object alive until we get the reply */
9514 	gtk_clipboard_request_targets (nemo_clipboard_get (GTK_WIDGET (view)),
9515 				       clipboard_targets_received,
9516 				       view);
9517 }
9518 
9519 static void
real_update_location_menu(NemoView * view)9520 real_update_location_menu (NemoView *view)
9521 {
9522 	GtkAction *action;
9523 	NemoFile *file;
9524 	gboolean is_special_link;
9525 	gboolean is_desktop_or_home_dir;
9526     gboolean is_recent;
9527 	gboolean can_delete_file, show_delete;
9528 	gboolean show_separate_delete_command;
9529 	gboolean show_open_in_new_tab;
9530 	gboolean show_open_alternate;
9531 	GList l;
9532 	char *label;
9533 	char *tip;
9534 
9535 	show_open_in_new_tab = g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_ALWAYS_USE_BROWSER);
9536 	show_open_alternate = g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_ALWAYS_USE_BROWSER);
9537 
9538 	action = gtk_action_group_get_action (view->details->dir_action_group,
9539 					      NEMO_ACTION_LOCATION_OPEN_ALTERNATE);
9540 	gtk_action_set_visible (action, show_open_alternate);
9541 
9542 	label = _("Open in New _Window");
9543 	g_object_set (action,
9544 		      "label", label,
9545 		      NULL);
9546 
9547 	action = gtk_action_group_get_action (view->details->dir_action_group,
9548 					      NEMO_ACTION_LOCATION_OPEN_IN_NEW_TAB);
9549 	gtk_action_set_visible (action, show_open_in_new_tab);
9550 
9551 	label = _("Open in New _Tab");
9552 	g_object_set (action,
9553 		      "label", label,
9554 		      NULL);
9555 
9556 	file = view->details->location_popup_directory_as_file;
9557 	g_assert (NEMO_IS_FILE (file));
9558 	g_assert (nemo_file_check_if_ready (file, NEMO_FILE_ATTRIBUTE_INFO |
9559 						NEMO_FILE_ATTRIBUTE_MOUNT |
9560 						NEMO_FILE_ATTRIBUTE_FILESYSTEM_INFO));
9561 
9562 	is_special_link = NEMO_IS_DESKTOP_ICON_FILE (file);
9563 	is_desktop_or_home_dir = nemo_file_is_home (file)
9564 		|| nemo_file_is_desktop_directory (file);
9565 
9566     is_recent = nemo_file_is_in_recent (file);
9567 
9568 	can_delete_file =
9569 		nemo_file_can_delete (file) &&
9570 		!is_special_link &&
9571 		!is_desktop_or_home_dir;
9572 
9573 	action = gtk_action_group_get_action (view->details->dir_action_group,
9574 					      NEMO_ACTION_LOCATION_CUT);
9575     gtk_action_set_sensitive (action, !is_recent && can_delete_file);
9576     gtk_action_set_visible (action, !is_recent);
9577 
9578 	action = gtk_action_group_get_action (view->details->dir_action_group,
9579 					      NEMO_ACTION_LOCATION_PASTE_FILES_INTO);
9580 	g_object_set_data (G_OBJECT (action),
9581 			   "can-paste-according-to-destination",
9582 			   GINT_TO_POINTER (can_paste_into_file (file)));
9583 	gtk_action_set_sensitive (action,
9584                               !is_recent &&
9585                               GPOINTER_TO_INT (g_object_get_data (G_OBJECT (action),
9586                                                "can-paste-according-to-clipboard")) &&
9587                               GPOINTER_TO_INT (g_object_get_data (G_OBJECT (action),
9588                                                "can-paste-according-to-destination")));
9589 
9590     gtk_action_set_visible (action, !is_recent);
9591 
9592 	show_delete = TRUE;
9593 
9594 	if (file != NULL &&
9595 	    nemo_file_is_in_trash (file)) {
9596 		if (nemo_file_is_self_owned (file)) {
9597 			show_delete = FALSE;
9598 		}
9599 
9600 		label = _("_Delete Permanently");
9601 		tip = _("Delete the open folder permanently");
9602 		show_separate_delete_command = FALSE;
9603 	} else {
9604 		label = _("Mo_ve to Trash");
9605 		tip = _("Move the open folder to the Trash");
9606 		show_separate_delete_command = g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_ENABLE_DELETE);
9607 	}
9608 
9609 	action = gtk_action_group_get_action (view->details->dir_action_group,
9610 					      NEMO_ACTION_LOCATION_TRASH);
9611 	g_object_set (action,
9612 		      "label", label,
9613 		      "tooltip", tip,
9614 		      "icon-name", (file != NULL &&
9615 				    nemo_file_is_in_trash (file)) ?
9616 		      NEMO_ICON_DELETE : NEMO_ICON_SYMBOLIC_TRASH_FULL,
9617 		      NULL);
9618 	gtk_action_set_sensitive (action, can_delete_file);
9619 	gtk_action_set_visible (action, show_delete);
9620 
9621 	action = gtk_action_group_get_action (view->details->dir_action_group,
9622 					      NEMO_ACTION_LOCATION_DELETE);
9623 	gtk_action_set_visible (action, show_separate_delete_command);
9624 	if (show_separate_delete_command) {
9625 		gtk_action_set_sensitive (action, can_delete_file);
9626 		g_object_set (action,
9627 			      "icon-name", NEMO_ICON_DELETE,
9628 			      "sensitive", can_delete_file,
9629 			      NULL);
9630 	}
9631 
9632 	action = gtk_action_group_get_action (view->details->dir_action_group,
9633 					      NEMO_ACTION_LOCATION_RESTORE_FROM_TRASH);
9634 	l.prev = NULL;
9635 	l.next = NULL;
9636 	l.data = file;
9637 	update_restore_from_trash_action (action, &l, TRUE);
9638 
9639 	real_update_location_menu_volumes (view);
9640 }
9641 
9642 static void
clipboard_changed_callback(NemoClipboardMonitor * monitor,NemoView * view)9643 clipboard_changed_callback (NemoClipboardMonitor *monitor, NemoView *view)
9644 {
9645 	GList *selection;
9646 	gint selection_count;
9647 
9648 	if (!view->details->active) {
9649 		return;
9650 	}
9651 
9652 	selection = nemo_view_get_selection (view);
9653 	selection_count = g_list_length (selection);
9654 
9655 	real_update_paste_menu (view, selection, selection_count);
9656 
9657 	nemo_file_list_free (selection);
9658 }
9659 
9660 static gboolean
can_delete_all(GList * files)9661 can_delete_all (GList *files)
9662 {
9663 	NemoFile *file;
9664 	GList *l;
9665 
9666 	for (l = files; l != NULL; l = l->next) {
9667 		file = l->data;
9668 		if (!nemo_file_can_delete (file)) {
9669 			return FALSE;
9670 		}
9671 	}
9672 	return TRUE;
9673 }
9674 
9675 static gboolean
has_writable_extra_pane(NemoView * view)9676 has_writable_extra_pane (NemoView *view)
9677 {
9678 	NemoView *other_view;
9679 
9680 	other_view = get_directory_view_of_extra_pane (view);
9681 	if (other_view != NULL) {
9682 		return !nemo_view_is_read_only (other_view);
9683 	}
9684 	return FALSE;
9685 }
9686 
9687 static void
update_configurable_context_menu_items(NemoView * view)9688 update_configurable_context_menu_items (NemoView *view)
9689 {
9690     GtkUIManager *ui_manager;
9691     GtkWidget *item;
9692     GtkAction *action;
9693     gint i;
9694 
9695     ui_manager = nemo_window_get_ui_manager (view->details->window);
9696 
9697     for (i = 0; i < CONFIGURABLE_MENU_ITEM_COUNT; i++) {
9698         if (!CONFIGURABLE_MENU_ITEM_INFO[i].action_name) {
9699             continue;
9700         }
9701 
9702         item = gtk_ui_manager_get_widget (ui_manager,
9703                                           CONFIGURABLE_MENU_ITEM_INFO[i].ui_path);
9704 
9705         action = gtk_ui_manager_get_action (ui_manager,
9706                                             CONFIGURABLE_MENU_ITEM_INFO[i].ui_path);
9707 
9708         if (!item || !action) {
9709             DEBUG ("Configurable menu item widget or action not found (name: %s, path: %s)",
9710                          CONFIGURABLE_MENU_ITEM_INFO[i].action_name,
9711                          CONFIGURABLE_MENU_ITEM_INFO[i].ui_path);
9712             continue;
9713         }
9714 
9715         gboolean pref_visible = g_settings_get_boolean (nemo_menu_config_preferences,
9716                                                         CONFIGURABLE_MENU_ITEM_INFO[i].settings_key);
9717 
9718         gtk_widget_set_visible (item, gtk_action_get_visible (action) && pref_visible);
9719     }
9720 }
9721 
9722 static void
real_update_menus(NemoView * view)9723 real_update_menus (NemoView *view)
9724 {
9725 	GList *selection, *l;
9726 	gint selection_count;
9727 	const char *tip, *label;
9728 	char *label_with_underscore;
9729 	gboolean selection_contains_special_link;
9730 	gboolean selection_contains_desktop_or_home_dir;
9731     gboolean selection_contains_recent;
9732     gboolean selection_contains_favorites;
9733     gboolean selection_contains_directory;
9734 	gboolean can_create_files;
9735 	gboolean can_delete_files;
9736 	gboolean can_copy_files;
9737 	gboolean can_link_files;
9738 	gboolean can_duplicate_files;
9739 	gboolean show_separate_delete_command;
9740 	gboolean show_open_alternate;
9741 	gboolean show_open_in_new_tab;
9742 	gboolean can_open;
9743 	gboolean show_app;
9744     gboolean showing_search;
9745 	gboolean show_save_search;
9746 	gboolean save_search_sensitive;
9747 	gboolean show_save_search_as;
9748 	gboolean show_desktop_target;
9749     gboolean is_desktop_view;
9750 	GtkAction *action;
9751 	GAppInfo *app;
9752 	GIcon *app_icon;
9753 	gboolean next_pane_is_writable;
9754 	gboolean show_properties;
9755     gboolean first_selected_is_pinned;
9756 
9757 	selection = nemo_view_get_selection (view);
9758 	selection_count = g_list_length (selection);
9759 
9760 	selection_contains_special_link = special_link_in_selection (view, selection);
9761 	selection_contains_desktop_or_home_dir = desktop_or_home_dir_in_selection (view, selection);
9762     selection_contains_recent = showing_recent_directory (view);
9763     selection_contains_favorites = showing_favorites_directory (view);
9764     selection_contains_directory = directory_in_selection (view, selection);
9765 	can_create_files = nemo_view_supports_creating_files (view);
9766 	can_delete_files =
9767 		can_delete_all (selection) &&
9768 		selection_count != 0 &&
9769 		!selection_contains_special_link &&
9770 		!selection_contains_desktop_or_home_dir;
9771 	can_copy_files = selection_count != 0
9772                      && !selection_contains_special_link;
9773 
9774 	can_duplicate_files = can_create_files && can_copy_files;
9775 	can_link_files = can_create_files && can_copy_files;
9776 
9777     is_desktop_view = get_is_desktop_view (view);
9778 
9779 	action = gtk_action_group_get_action (view->details->dir_action_group,
9780 					      NEMO_ACTION_RENAME);
9781 	/* rename sensitivity depending on selection */
9782 	if (selection_count > 1) {
9783 		/* If multiple files are selected, sensitivity depends on whether a bulk renamer is registered. */
9784 		gtk_action_set_sensitive (action, have_bulk_rename_tool ());
9785 	} else {
9786 		gtk_action_set_sensitive (action,
9787 					  selection_count == 1 &&
9788 					  nemo_view_can_rename_file (view, selection->data));
9789 	}
9790 
9791     gtk_action_set_visible (action, !selection_contains_recent &&
9792                                     !selection_contains_special_link);
9793 
9794     gboolean no_selection_or_one_dir = ((selection_count == 1 && selection_contains_directory) ||
9795                                         selection_count == 0);
9796 
9797     gboolean show_open_as_root = (geteuid() != 0) && no_selection_or_one_dir;
9798 
9799     action = gtk_action_group_get_action (view->details->dir_action_group,
9800                                          NEMO_ACTION_OPEN_AS_ROOT);
9801     gtk_action_set_visible (action, show_open_as_root);
9802 
9803     action = gtk_action_group_get_action (view->details->dir_action_group,
9804                                          NEMO_ACTION_OPEN_IN_TERMINAL);
9805     gtk_action_set_visible (action, no_selection_or_one_dir);
9806 
9807 	action = gtk_action_group_get_action (view->details->dir_action_group,
9808 					      NEMO_ACTION_NEW_FOLDER);
9809 	gtk_action_set_sensitive (action, can_create_files);
9810     gtk_action_set_visible (action, !selection_contains_recent && !selection_contains_favorites);
9811 
9812 	can_open = show_app = selection_count != 0;
9813 
9814 	for (l = selection; l != NULL; l = l->next) {
9815 		NemoFile *file;
9816 
9817 		file = NEMO_FILE (selection->data);
9818 
9819 		if (!nemo_mime_file_opens_in_external_app (file)) {
9820 			show_app = FALSE;
9821 		}
9822 
9823 		if (!show_app) {
9824 			break;
9825 		}
9826 	}
9827 
9828 	label_with_underscore = NULL;
9829 
9830 	app = NULL;
9831 	app_icon = NULL;
9832 
9833 	if (can_open && show_app) {
9834 		app = nemo_mime_get_default_application_for_files (selection);
9835 	}
9836 
9837 	if (app != NULL) {
9838 		char *escaped_app;
9839 
9840 		escaped_app = eel_str_double_underscores (g_app_info_get_name (app));
9841 		label_with_underscore = g_strdup_printf (_("_Open With %s"),
9842 							 escaped_app);
9843 
9844 		app_icon = g_app_info_get_icon (app);
9845 		if (app_icon != NULL) {
9846 			g_object_ref (app_icon);
9847 		}
9848 
9849 		g_free (escaped_app);
9850 		g_object_unref (app);
9851 	}
9852 
9853     if (app_icon == NULL) {
9854         app_icon = g_themed_icon_new ("folder-open-symbolic");
9855     }
9856 
9857     action = gtk_action_group_get_action (view->details->dir_action_group,
9858                           NEMO_ACTION_OPEN);
9859     gtk_action_set_sensitive (action, selection_count != 0);
9860 
9861     g_object_set (action, "label",
9862               label_with_underscore ? label_with_underscore : _("_Open"),
9863               NULL);
9864 
9865     gtk_action_set_gicon (action, app_icon);
9866     gtk_action_set_visible (action, can_open);
9867 
9868     g_object_unref (app_icon);
9869     g_free (label_with_underscore);
9870 
9871     menu_item_show_image (nemo_window_get_ui_manager (view->details->window),
9872                           NEMO_VIEW_MENU_PATH_OPEN_PLACEHOLDER,
9873                           NEMO_ACTION_OPEN,
9874                           FALSE);
9875 
9876 	show_open_alternate = file_list_all_are_folders (selection) &&
9877 		selection_count > 0 &&
9878 		g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_ALWAYS_USE_BROWSER) &&
9879 		!is_desktop_view;
9880 
9881 	action = gtk_action_group_get_action (view->details->dir_action_group,
9882 					      NEMO_ACTION_OPEN_ALTERNATE);
9883 
9884 	gtk_action_set_sensitive (action,  selection_count != 0);
9885 	gtk_action_set_visible (action, show_open_alternate);
9886 
9887 	if (selection_count == 0 || selection_count == 1) {
9888 		label_with_underscore = g_strdup (_("Open in New _Window"));
9889 	} else {
9890 		label_with_underscore = g_strdup_printf (ngettext("Open in %'d New _Window",
9891 								  "Open in %'d New _Windows",
9892 								  selection_count),
9893 							 selection_count);
9894 	}
9895 
9896 	g_object_set (action, "label",
9897 		      label_with_underscore,
9898 		      NULL);
9899 	g_free (label_with_underscore);
9900 
9901 	show_open_in_new_tab = show_open_alternate;
9902 	action = gtk_action_group_get_action (view->details->dir_action_group,
9903 					      NEMO_ACTION_OPEN_IN_NEW_TAB);
9904 	gtk_action_set_sensitive (action, selection_count != 0);
9905 	gtk_action_set_visible (action, show_open_in_new_tab);
9906 
9907 	if (selection_count == 0 || selection_count == 1) {
9908 		label_with_underscore = g_strdup (_("Open in New _Tab"));
9909 	} else {
9910 		label_with_underscore = g_strdup_printf (ngettext("Open in %'d New _Tab",
9911 								  "Open in %'d New _Tabs",
9912 								  selection_count),
9913 							 selection_count);
9914 	}
9915 
9916 	g_object_set (action, "label",
9917 		      label_with_underscore,
9918 		      NULL);
9919 	g_free (label_with_underscore);
9920 
9921 	/* Broken into its own function just for convenience */
9922 	reset_open_with_menu (view, selection, show_app);
9923 	reset_extension_actions_menu (view, selection);
9924     reset_move_copy_to_menu (view);
9925 
9926 	if (all_selected_items_in_trash (view, selection)) {
9927 		label = _("_Delete Permanently");
9928 		tip = _("Delete all selected items permanently");
9929 		show_separate_delete_command = FALSE;
9930 	} else {
9931 		label = _("Mo_ve to Trash");
9932 		tip = _("Move each selected item to the Trash");
9933 		show_separate_delete_command = g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_ENABLE_DELETE);
9934 	}
9935 
9936 	action = gtk_action_group_get_action (view->details->dir_action_group,
9937 					      NEMO_ACTION_TRASH);
9938 	g_object_set (action,
9939 		      "label", label,
9940 		      "tooltip", tip,
9941 		      "icon-name", all_selected_items_in_trash (view, selection) ?
9942 		      NEMO_ICON_DELETE : NEMO_ICON_SYMBOLIC_TRASH_FULL,
9943 		      NULL);
9944 	gtk_action_set_sensitive (action, can_delete_files);
9945     gtk_action_set_visible (action, !(selection_contains_favorites || selection_contains_recent));
9946 
9947 	action = gtk_action_group_get_action (view->details->dir_action_group,
9948 					      NEMO_ACTION_DELETE);
9949 	gtk_action_set_visible (action, show_separate_delete_command && !selection_contains_favorites);
9950 
9951     if (selection_contains_recent) {
9952         label = _("Remo_ve from Recent");
9953         tip = _("Remove each selected item from the recently used list");
9954     } else {
9955         label = _("_Delete");
9956         tip = _("Delete each selected item, without moving to the Trash");
9957     }
9958 
9959 	if (show_separate_delete_command) {
9960 		g_object_set (action,
9961 			      "label", label,
9962                   "tooltip", tip,
9963 			      "icon-name", NEMO_ICON_DELETE,
9964 			      NULL);
9965 	}
9966 	gtk_action_set_sensitive (action, can_delete_files);
9967 
9968 	action = gtk_action_group_get_action (view->details->dir_action_group,
9969 					      NEMO_ACTION_RESTORE_FROM_TRASH);
9970 	update_restore_from_trash_action (action, selection, FALSE);
9971 
9972 	action = gtk_action_group_get_action (view->details->dir_action_group, NEMO_ACTION_DUPLICATE);
9973 	gtk_action_set_sensitive (action, can_duplicate_files);
9974     gtk_action_set_visible (action, !selection_contains_recent && !selection_contains_favorites);
9975 
9976 	action = gtk_action_group_get_action (view->details->dir_action_group,
9977 					      NEMO_ACTION_CREATE_LINK);
9978 	gtk_action_set_sensitive (action, can_link_files);
9979     gtk_action_set_visible (action, !selection_contains_recent && !selection_contains_favorites);
9980 	g_object_set (action, "label",
9981 		      ngettext ("Ma_ke Link",
9982 			      	"Ma_ke Links",
9983 				selection_count),
9984 		      NULL);
9985 
9986 	show_properties = (!is_desktop_view || selection_count > 0);
9987 
9988 	action = gtk_action_group_get_action (view->details->dir_action_group,
9989 					      NEMO_ACTION_PROPERTIES);
9990 
9991 	gtk_action_set_sensitive (action, show_properties);
9992 
9993 	if (selection_count == 0) {
9994 		gtk_action_set_tooltip (action, _("View or modify the properties of the open folder"));
9995 	} else {
9996 		gtk_action_set_tooltip (action, _("View or modify the properties of each selected item"));
9997 	}
9998 
9999 	gtk_action_set_visible (action, show_properties);
10000 
10001 	action = gtk_action_group_get_action (view->details->dir_action_group,
10002 					      NEMO_ACTION_PROPERTIES_ACCEL);
10003 
10004 	gtk_action_set_sensitive (action, show_properties);
10005 
10006 	action = gtk_action_group_get_action (view->details->dir_action_group,
10007 					      NEMO_ACTION_EMPTY_TRASH);
10008 	g_object_set (action,
10009 		      "label", _("E_mpty Trash"),
10010 		      NULL);
10011 	gtk_action_set_sensitive (action, !nemo_trash_monitor_is_empty ());
10012 	gtk_action_set_visible (action, should_show_empty_trash (view));
10013 
10014     showing_search = view->details->model && NEMO_IS_SEARCH_DIRECTORY (view->details->model);
10015 
10016 	show_save_search = FALSE;
10017 	save_search_sensitive = FALSE;
10018 	show_save_search_as = FALSE;
10019 	if (showing_search) {
10020 		NemoSearchDirectory *search;
10021 
10022 		search = NEMO_SEARCH_DIRECTORY (view->details->model);
10023 		if (nemo_search_directory_is_saved_search (search)) {
10024 			show_save_search = TRUE;
10025 			save_search_sensitive = nemo_search_directory_is_modified (search);
10026 		} else {
10027 			show_save_search_as = TRUE;
10028 		}
10029 	}
10030 	action = gtk_action_group_get_action (view->details->dir_action_group,
10031 					      NEMO_ACTION_SAVE_SEARCH);
10032 	gtk_action_set_visible (action, show_save_search);
10033 	gtk_action_set_sensitive (action, save_search_sensitive);
10034 	action = gtk_action_group_get_action (view->details->dir_action_group,
10035 					      NEMO_ACTION_SAVE_SEARCH_AS);
10036 	gtk_action_set_visible (action, show_save_search_as);
10037 
10038 
10039 	action = gtk_action_group_get_action (view->details->dir_action_group,
10040 					      NEMO_ACTION_SELECT_ALL);
10041 	gtk_action_set_sensitive (action, !nemo_view_is_empty (view));
10042 
10043 	action = gtk_action_group_get_action (view->details->dir_action_group,
10044 					      NEMO_ACTION_SELECT_PATTERN);
10045 	gtk_action_set_sensitive (action, !nemo_view_is_empty (view));
10046 
10047 	action = gtk_action_group_get_action (view->details->dir_action_group,
10048 					      NEMO_ACTION_INVERT_SELECTION);
10049 	gtk_action_set_sensitive (action, !nemo_view_is_empty (view));
10050 
10051 	action = gtk_action_group_get_action (view->details->dir_action_group,
10052 					      NEMO_ACTION_CUT);
10053 	gtk_action_set_sensitive (action, can_delete_files);
10054     gtk_action_set_visible (action, !selection_contains_recent && !selection_contains_favorites);
10055 
10056 	action = gtk_action_group_get_action (view->details->dir_action_group,
10057 					      NEMO_ACTION_COPY);
10058 	gtk_action_set_sensitive (action, can_copy_files);
10059 
10060 	real_update_paste_menu (view, selection, selection_count);
10061 
10062 	real_update_menus_volumes (view, selection, selection_count);
10063 
10064 	update_undo_actions (view);
10065 
10066 	if (view->details->scripts_invalid) {
10067 		update_scripts_menu (view);
10068 	}
10069 
10070 	action = gtk_action_group_get_action (view->details->dir_action_group,
10071 					      NEMO_ACTION_NEW_DOCUMENTS);
10072 	gtk_action_set_sensitive (action, can_create_files);
10073     gtk_action_set_visible (action, !selection_contains_recent && !selection_contains_favorites);
10074 
10075 	if (can_create_files && view->details->templates_invalid) {
10076 		update_templates_menu (view);
10077 	}
10078 
10079     if (view->details->actions_invalid) {
10080         update_actions_menu (view);
10081     }
10082 
10083     update_actions_visibility (view, selection);
10084 
10085 	next_pane_is_writable = has_writable_extra_pane (view);
10086 
10087 	/* next pane: works if file is copyable, and next pane is writable */
10088 	action = gtk_action_group_get_action (view->details->dir_action_group,
10089 					      NEMO_ACTION_COPY_TO_NEXT_PANE);
10090 	gtk_action_set_visible (action, can_copy_files && next_pane_is_writable);
10091 
10092 	/* move to next pane: works if file is cuttable, and next pane is writable */
10093 	action = gtk_action_group_get_action (view->details->dir_action_group,
10094 					      NEMO_ACTION_MOVE_TO_NEXT_PANE);
10095 	gtk_action_set_visible (action, can_delete_files &&
10096                             next_pane_is_writable &&
10097                             !selection_contains_recent &&
10098                             !selection_contains_favorites);
10099 
10100 	show_desktop_target =
10101 		g_settings_get_boolean (nemo_desktop_preferences, NEMO_PREFERENCES_SHOW_DESKTOP) &&
10102 		!g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_DESKTOP_IS_HOME_DIR);
10103 
10104 	action = gtk_action_group_get_action (view->details->dir_action_group,
10105 					      NEMO_ACTION_COPY_TO_HOME);
10106 	gtk_action_set_sensitive (action, can_copy_files);
10107 
10108 	action = gtk_action_group_get_action (view->details->dir_action_group,
10109 					      NEMO_ACTION_COPY_TO_DESKTOP);
10110 	gtk_action_set_sensitive (action, can_copy_files);
10111 	gtk_action_set_visible (action, show_desktop_target);
10112 
10113 	action = gtk_action_group_get_action (view->details->dir_action_group,
10114 					      NEMO_ACTION_MOVE_TO_HOME);
10115 	gtk_action_set_sensitive (action, can_delete_files);
10116     gtk_action_set_visible (action, !selection_contains_recent && !selection_contains_favorites);
10117 	action = gtk_action_group_get_action (view->details->dir_action_group,
10118 					      NEMO_ACTION_MOVE_TO_DESKTOP);
10119 	gtk_action_set_sensitive (action, can_delete_files);
10120 	gtk_action_set_visible (action, show_desktop_target &&
10121                             !selection_contains_recent &&
10122                             !selection_contains_favorites);
10123 
10124 	action = gtk_action_group_get_action (view->details->dir_action_group,
10125 					      "CopyToMenu");
10126 	gtk_action_set_sensitive (action, can_copy_files);
10127 
10128 	action = gtk_action_group_get_action (view->details->dir_action_group,
10129 					      "MoveToMenu");
10130 	gtk_action_set_sensitive (action, can_delete_files);
10131     gtk_action_set_visible (action, !selection_contains_recent && !selection_contains_favorites);
10132 
10133     action = gtk_action_group_get_action (view->details->dir_action_group,
10134                                           NEMO_ACTION_FOLLOW_SYMLINK);
10135     gtk_action_set_visible (action,
10136                             selection_count == 1 &&
10137                             nemo_file_is_symbolic_link (selection->data) &&
10138                             !selection_contains_favorites);
10139 
10140     action = gtk_action_group_get_action (view->details->dir_action_group,
10141                                           NEMO_ACTION_OPEN_CONTAINING_FOLDER);
10142 
10143     gtk_action_set_visible (action,
10144                             selection_count == 1 &&
10145                             (selection_contains_recent || selection_contains_favorites || showing_search));
10146 
10147     first_selected_is_pinned = selection_count > 0 &&
10148                                nemo_file_get_pinning (NEMO_FILE (selection->data));
10149 
10150     action = gtk_action_group_get_action (view->details->dir_action_group,
10151                                           NEMO_ACTION_PIN_FILE);
10152 
10153     gtk_action_set_visible (action, !is_desktop_view && !first_selected_is_pinned && !(selection_contains_recent || selection_contains_favorites));
10154 
10155     action = gtk_action_group_get_action (view->details->dir_action_group,
10156                                           NEMO_ACTION_UNPIN_FILE);
10157 
10158     gtk_action_set_visible (action, !is_desktop_view && first_selected_is_pinned && !(selection_contains_recent || selection_contains_favorites));
10159 
10160     action = gtk_action_group_get_action (view->details->dir_action_group,
10161                                           NEMO_ACTION_FAVORITE_FILE);
10162 
10163     gboolean first_selected_is_favorite = selection_count > 0 &&
10164                                           nemo_file_get_is_favorite (NEMO_FILE (selection->data));
10165 
10166     if (selection_contains_favorites) {
10167         gtk_action_set_visible (action, FALSE);
10168     } else {
10169         gtk_action_set_visible (action, !is_desktop_view && !first_selected_is_favorite && !selection_contains_recent);
10170     }
10171 
10172     action = gtk_action_group_get_action (view->details->dir_action_group,
10173                                           NEMO_ACTION_UNFAVORITE_FILE);
10174 
10175     if (selection_contains_favorites) {
10176         gtk_action_set_visible (action, TRUE);
10177     } else {
10178         gtk_action_set_visible (action, !is_desktop_view && first_selected_is_favorite && !selection_contains_recent);
10179     }
10180 
10181     update_configurable_context_menu_items (view);
10182 
10183     nemo_file_list_free (selection);
10184 }
10185 
10186 /**
10187  * nemo_view_pop_up_selection_context_menu
10188  *
10189  * Pop up a context menu appropriate to the selected items.
10190  * @view: NemoView of interest.
10191  * @event: The event that triggered this context menu.
10192  *
10193  * Return value: NemoDirectory for this view.
10194  *
10195  **/
10196 void
nemo_view_pop_up_selection_context_menu(NemoView * view,GdkEventButton * event)10197 nemo_view_pop_up_selection_context_menu  (NemoView *view,
10198 					      GdkEventButton  *event)
10199 {
10200 	g_assert (NEMO_IS_VIEW (view));
10201 
10202 	/* Make the context menu items not flash as they update to proper disabled,
10203 	 * etc. states by forcing menus to update now.
10204 	 */
10205 	update_menus_if_pending (view);
10206 
10207 	update_context_menu_position_from_event (view, event);
10208 
10209 	eel_pop_up_context_menu (create_popup_menu
10210 				 (view, NEMO_VIEW_POPUP_PATH_SELECTION),
10211 				 event);
10212 }
10213 
10214 /**
10215  * nemo_view_pop_up_background_context_menu
10216  *
10217  * Pop up a context menu appropriate to the view globally at the last right click location.
10218  * @view: NemoView of interest.
10219  *
10220  * Return value: NemoDirectory for this view.
10221  *
10222  **/
10223 void
nemo_view_pop_up_background_context_menu(NemoView * view,GdkEventButton * event)10224 nemo_view_pop_up_background_context_menu (NemoView *view,
10225 					      GdkEventButton  *event)
10226 {
10227 	g_assert (NEMO_IS_VIEW (view));
10228 
10229 	/* Make the context menu items not flash as they update to proper disabled,
10230 	 * etc. states by forcing menus to update now.
10231 	 */
10232 	update_menus_if_pending (view);
10233 
10234 	update_context_menu_position_from_event (view, event);
10235 
10236 
10237 	eel_pop_up_context_menu (create_popup_menu
10238 				 (view, NEMO_VIEW_POPUP_PATH_BACKGROUND),
10239 				 event);
10240 }
10241 
10242 static void
real_pop_up_location_context_menu(NemoView * view)10243 real_pop_up_location_context_menu (NemoView *view)
10244 {
10245 	/* always update the menu before showing it. Shouldn't be too expensive. */
10246 	real_update_location_menu (view);
10247 
10248 	update_context_menu_position_from_event (view, view->details->location_popup_event);
10249 
10250 	eel_pop_up_context_menu (create_popup_menu
10251 				 (view, NEMO_VIEW_POPUP_PATH_LOCATION),
10252 				 view->details->location_popup_event);
10253 }
10254 
10255 static void
location_popup_file_attributes_ready(NemoFile * file,gpointer data)10256 location_popup_file_attributes_ready (NemoFile *file,
10257 				      gpointer      data)
10258 {
10259 	NemoView *view;
10260 
10261 	view = NEMO_VIEW (data);
10262 	g_assert (NEMO_IS_VIEW (view));
10263 
10264 	g_assert (file == view->details->location_popup_directory_as_file);
10265 
10266 	real_pop_up_location_context_menu (view);
10267 }
10268 
10269 static void
unschedule_pop_up_location_context_menu(NemoView * view)10270 unschedule_pop_up_location_context_menu (NemoView *view)
10271 {
10272 	if (view->details->location_popup_directory_as_file != NULL) {
10273 		g_assert (NEMO_IS_FILE (view->details->location_popup_directory_as_file));
10274 		nemo_file_cancel_call_when_ready (view->details->location_popup_directory_as_file,
10275 						      location_popup_file_attributes_ready,
10276 						      view);
10277 		nemo_file_unref (view->details->location_popup_directory_as_file);
10278 		view->details->location_popup_directory_as_file = NULL;
10279 	}
10280 }
10281 
10282 static void
schedule_pop_up_location_context_menu(NemoView * view,GdkEventButton * event,NemoFile * file)10283 schedule_pop_up_location_context_menu (NemoView *view,
10284 				       GdkEventButton  *event,
10285 				       NemoFile    *file)
10286 {
10287 	g_assert (NEMO_IS_FILE (file));
10288 
10289 	if (view->details->location_popup_event != NULL) {
10290 		gdk_event_free ((GdkEvent *) view->details->location_popup_event);
10291 	}
10292 	view->details->location_popup_event = (GdkEventButton *) gdk_event_copy ((GdkEvent *)event);
10293 
10294 	if (file == view->details->location_popup_directory_as_file) {
10295 		if (nemo_file_check_if_ready (file, NEMO_FILE_ATTRIBUTE_INFO |
10296 						  NEMO_FILE_ATTRIBUTE_MOUNT |
10297 						  NEMO_FILE_ATTRIBUTE_FILESYSTEM_INFO)) {
10298 			real_pop_up_location_context_menu (view);
10299 		}
10300 	} else {
10301 		unschedule_pop_up_location_context_menu (view);
10302 
10303 		view->details->location_popup_directory_as_file = nemo_file_ref (file);
10304 		nemo_file_call_when_ready (view->details->location_popup_directory_as_file,
10305 					       NEMO_FILE_ATTRIBUTE_INFO |
10306 					       NEMO_FILE_ATTRIBUTE_MOUNT |
10307 					       NEMO_FILE_ATTRIBUTE_FILESYSTEM_INFO,
10308 					       location_popup_file_attributes_ready,
10309 					       view);
10310 	}
10311 }
10312 
10313 /**
10314  * nemo_view_pop_up_location_context_menu
10315  *
10316  * Pop up a context menu appropriate to the view globally.
10317  * @view: NemoView of interest.
10318  * @event: GdkEventButton triggering the popup.
10319  * @location: The location the popup-menu should be created for,
10320  * or NULL for the currently displayed location.
10321  *
10322  **/
10323 void
nemo_view_pop_up_location_context_menu(NemoView * view,GdkEventButton * event,const char * location)10324 nemo_view_pop_up_location_context_menu (NemoView *view,
10325 					    GdkEventButton  *event,
10326 					    const char      *location)
10327 {
10328 	NemoFile *file;
10329 
10330 	g_assert (NEMO_IS_VIEW (view));
10331 
10332 	if (location != NULL) {
10333 		file = nemo_file_get_by_uri (location);
10334 	} else {
10335 		file = nemo_file_ref (view->details->directory_as_file);
10336 	}
10337 
10338 	if (file != NULL) {
10339 		schedule_pop_up_location_context_menu (view, event, file);
10340 		nemo_file_unref (file);
10341 	}
10342 }
10343 
10344 static void
schedule_update_menus(NemoView * view)10345 schedule_update_menus (NemoView *view)
10346 {
10347 	g_assert (NEMO_IS_VIEW (view));
10348 	/* Don't schedule updates after destroy (#349551),
10349  	 * or if we are not active.
10350 	 */
10351 	if (view->details->window == NULL ||
10352 	    !view->details->active) {
10353 		return;
10354 	}
10355 
10356 	view->details->menu_states_untrustworthy = TRUE;
10357 	/* Schedule a menu update with the current update interval */
10358     if (view->details->update_menus_timeout_id != 0) {
10359         g_source_remove (view->details->update_menus_timeout_id);
10360         view->details->update_menus_timeout_id = 0;
10361     }
10362     view->details->update_menus_timeout_id = g_timeout_add (view->details->update_interval,
10363                                                             update_menus_timeout_callback,
10364                                                             view);
10365 }
10366 
10367 static void
remove_update_status_idle_callback(NemoView * view)10368 remove_update_status_idle_callback (NemoView *view)
10369 {
10370 	if (view->details->update_status_idle_id != 0) {
10371 		g_source_remove (view->details->update_status_idle_id);
10372 		view->details->update_status_idle_id = 0;
10373 	}
10374 }
10375 
10376 static gboolean
update_status_idle_callback(gpointer data)10377 update_status_idle_callback (gpointer data)
10378 {
10379 	NemoView *view;
10380 
10381 	view = NEMO_VIEW (data);
10382 	nemo_view_display_selection_info (view);
10383 	view->details->update_status_idle_id = 0;
10384 	return FALSE;
10385 }
10386 
10387 static void
schedule_update_status(NemoView * view)10388 schedule_update_status (NemoView *view)
10389 {
10390 	g_assert (NEMO_IS_VIEW (view));
10391 
10392 	/* Make sure we haven't already destroyed it */
10393 	if (view->details->window == NULL) {
10394 		return;
10395 	}
10396 
10397 	if (view->details->loading) {
10398 		/* Don't update status bar while loading the dir */
10399 		return;
10400 	}
10401 
10402 	if (view->details->update_status_idle_id == 0) {
10403 		view->details->update_status_idle_id =
10404 			g_idle_add_full (G_PRIORITY_DEFAULT_IDLE - 20,
10405 					 update_status_idle_callback, view, NULL);
10406 	}
10407 }
10408 
10409 /**
10410  * nemo_view_notify_selection_changed:
10411  *
10412  * Notify this view that the selection has changed. This is normally
10413  * called only by subclasses.
10414  * @view: NemoView whose selection has changed.
10415  *
10416  **/
10417 void
nemo_view_notify_selection_changed(NemoView * view)10418 nemo_view_notify_selection_changed (NemoView *view)
10419 {
10420 	GtkWindow *window;
10421 	GList *selection;
10422 
10423 	g_return_if_fail (NEMO_IS_VIEW (view));
10424 
10425 	selection = nemo_view_get_selection (view);
10426 	window = nemo_view_get_containing_window (view);
10427 	DEBUG_FILES (selection, "Selection changed in window %p", window);
10428     nemo_file_list_free (selection);
10429 
10430 	view->details->selection_was_removed = FALSE;
10431 
10432 	if (!view->details->selection_change_is_due_to_shell) {
10433 		view->details->send_selection_change_to_shell = TRUE;
10434 	}
10435 
10436 	/* Schedule a display of the new selection. */
10437     if (view->details->display_selection_idle_id != 0) {
10438         g_source_remove (view->details->display_selection_idle_id);
10439         view->details->display_selection_idle_id = 0;
10440         nemo_window_slot_set_status (view->details->slot, "", "");
10441     }
10442     view->details->display_selection_idle_id = g_timeout_add (100,
10443                                                               display_selection_info_idle_callback,
10444                                                               view);
10445 
10446 	if (view->details->batching_selection_level != 0) {
10447 		view->details->selection_changed_while_batched = TRUE;
10448 	} else {
10449 		/* Here is the work we do only when we're not
10450 		 * batching selection changes. In other words, it's the slower
10451 		 * stuff that we don't want to slow down selection techniques
10452 		 * such as rubberband-selecting in icon view.
10453 		 */
10454 
10455 		/* Schedule an update of menu item states to match selection */
10456 		schedule_update_menus (view);
10457 	}
10458 }
10459 
10460 static void
file_changed_callback(NemoFile * file,gpointer callback_data)10461 file_changed_callback (NemoFile *file, gpointer callback_data)
10462 {
10463 	NemoView *view = NEMO_VIEW (callback_data);
10464 
10465 	schedule_changes (view);
10466 
10467 	schedule_update_menus (view);
10468 	schedule_update_status (view);
10469 }
10470 
10471 /**
10472  * load_directory:
10473  *
10474  * Switch the displayed location to a new uri. If the uri is not valid,
10475  * the location will not be switched; user feedback will be provided instead.
10476  * @view: NemoView whose location will be changed.
10477  * @uri: A string representing the uri to switch to.
10478  *
10479  **/
10480 static void
load_directory(NemoView * view,NemoDirectory * directory)10481 load_directory (NemoView *view,
10482 		NemoDirectory *directory)
10483 {
10484 	NemoDirectory *old_directory;
10485 	NemoFile *old_file;
10486 	NemoFileAttributes attributes;
10487 
10488 	g_assert (NEMO_IS_VIEW (view));
10489 	g_assert (NEMO_IS_DIRECTORY (directory));
10490 
10491 	nemo_view_stop_loading (view);
10492 	g_signal_emit (view, signals[CLEAR], 0);
10493 
10494 	view->details->loading = TRUE;
10495 
10496 	/* Update menus when directory is empty, before going to new
10497 	 * location, so they won't have any false lingering knowledge
10498 	 * of old selection.
10499 	 */
10500 	schedule_update_menus (view);
10501 
10502 	while (view->details->subdirectory_list != NULL) {
10503 		nemo_view_remove_subdirectory (view,
10504 						   view->details->subdirectory_list->data);
10505 	}
10506 
10507 	disconnect_model_handlers (view);
10508 
10509 	old_directory = view->details->model;
10510 	nemo_directory_ref (directory);
10511 	view->details->model = directory;
10512 	nemo_directory_unref (old_directory);
10513 
10514 	old_file = view->details->directory_as_file;
10515 	view->details->directory_as_file =
10516 		nemo_directory_get_corresponding_file (directory);
10517 	nemo_file_unref (old_file);
10518 
10519 	view->details->reported_load_error = FALSE;
10520 
10521 	/* FIXME bugzilla.gnome.org 45062: In theory, we also need to monitor metadata here (as
10522          * well as doing a call when ready), in case external forces
10523          * change the directory's file metadata.
10524 	 */
10525 	attributes =
10526 		NEMO_FILE_ATTRIBUTE_INFO |
10527 		NEMO_FILE_ATTRIBUTE_MOUNT |
10528 		NEMO_FILE_ATTRIBUTE_FILESYSTEM_INFO;
10529 	view->details->metadata_for_directory_as_file_pending = TRUE;
10530 	view->details->metadata_for_files_in_directory_pending = TRUE;
10531 	nemo_file_call_when_ready
10532 		(view->details->directory_as_file,
10533 		 attributes,
10534 		 metadata_for_directory_as_file_ready_callback, view);
10535 	nemo_directory_call_when_ready
10536 		(view->details->model,
10537 		 attributes,
10538 		 FALSE,
10539 		 metadata_for_files_in_directory_ready_callback, view);
10540 
10541 	/* If capabilities change, then we need to update the menus
10542 	 * because of New Folder, and relative emblems.
10543 	 */
10544 	attributes =
10545 		NEMO_FILE_ATTRIBUTE_INFO |
10546 		NEMO_FILE_ATTRIBUTE_FILESYSTEM_INFO;
10547 	nemo_file_monitor_add (view->details->directory_as_file,
10548 				   &view->details->directory_as_file,
10549 				   attributes);
10550 
10551 	view->details->file_changed_handler_id = g_signal_connect
10552 		(view->details->directory_as_file, "changed",
10553 		 G_CALLBACK (file_changed_callback), view);
10554 }
10555 
10556 static void
finish_loading(NemoView * view)10557 finish_loading (NemoView *view)
10558 {
10559 	NemoFileAttributes attributes;
10560 
10561 	nemo_window_report_load_underway (view->details->window,
10562 					      NEMO_VIEW (view));
10563 
10564     g_timer_start (view->details->load_timer);
10565 
10566 	/* Tell interested parties that we've begun loading this directory now.
10567 	 * Subclasses use this to know that the new metadata is now available.
10568 	 */
10569 	g_signal_emit (view, signals[BEGIN_LOADING], 0);
10570 
10571 	/* Assume we have now all information to show window */
10572 	nemo_window_view_visible  (view->details->window, NEMO_VIEW (view));
10573 
10574 	if (nemo_directory_are_all_files_seen (view->details->model)) {
10575 		/* Unschedule a pending update and schedule a new one with the minimal
10576 		 * update interval. This gives the view a short chance at gathering the
10577 		 * (cached) deep counts.
10578 		 */
10579 		unschedule_display_of_pending_files (view);
10580 		schedule_timeout_display_of_pending_files (view, UPDATE_INTERVAL_MIN);
10581 	}
10582 
10583 	/* Start loading. */
10584 
10585 	/* Connect handlers to learn about loading progress. */
10586 	view->details->done_loading_handler_id = g_signal_connect
10587 		(view->details->model, "done_loading",
10588 		 G_CALLBACK (done_loading_callback), view);
10589 	view->details->load_error_handler_id = g_signal_connect
10590 		(view->details->model, "load_error",
10591 		 G_CALLBACK (load_error_callback), view);
10592 
10593 	/* Monitor the things needed to get the right icon. Also
10594 	 * monitor a directory's item count because the "size"
10595 	 * attribute is based on that, and the file's metadata
10596 	 * and possible custom name.
10597 	 */
10598 	attributes =
10599 		NEMO_FILE_ATTRIBUTES_FOR_ICON |
10600 		NEMO_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT |
10601 		NEMO_FILE_ATTRIBUTE_INFO |
10602 		NEMO_FILE_ATTRIBUTE_LINK_INFO |
10603 		NEMO_FILE_ATTRIBUTE_MOUNT |
10604 		NEMO_FILE_ATTRIBUTE_EXTENSION_INFO |
10605         NEMO_FILE_ATTRIBUTE_BTIME |
10606         NEMO_FILE_ATTRIBUTE_FAVORITE_CHECK;
10607 
10608 	nemo_directory_file_monitor_add (view->details->model,
10609 					     &view->details->model,
10610 					     view->details->show_hidden_files,
10611 					     attributes,
10612 					     files_added_callback, view);
10613 
10614     	view->details->files_added_handler_id = g_signal_connect
10615 		(view->details->model, "files_added",
10616 		 G_CALLBACK (files_added_callback), view);
10617 	view->details->files_changed_handler_id = g_signal_connect
10618 		(view->details->model, "files_changed",
10619 		 G_CALLBACK (files_changed_callback), view);
10620 }
10621 
10622 static void
finish_loading_if_all_metadata_loaded(NemoView * view)10623 finish_loading_if_all_metadata_loaded (NemoView *view)
10624 {
10625 	if (!view->details->metadata_for_directory_as_file_pending &&
10626 	    !view->details->metadata_for_files_in_directory_pending) {
10627 		finish_loading (view);
10628 	}
10629 }
10630 
10631 static void
metadata_for_directory_as_file_ready_callback(NemoFile * file,gpointer callback_data)10632 metadata_for_directory_as_file_ready_callback (NemoFile *file,
10633 			      		       gpointer callback_data)
10634 {
10635 	NemoView *view;
10636 
10637 	view = callback_data;
10638 
10639 	g_assert (NEMO_IS_VIEW (view));
10640 	g_assert (view->details->directory_as_file == file);
10641 	g_assert (view->details->metadata_for_directory_as_file_pending);
10642 
10643 	view->details->metadata_for_directory_as_file_pending = FALSE;
10644 
10645 	finish_loading_if_all_metadata_loaded (view);
10646 }
10647 
10648 static void
metadata_for_files_in_directory_ready_callback(NemoDirectory * directory,GList * files,gpointer callback_data)10649 metadata_for_files_in_directory_ready_callback (NemoDirectory *directory,
10650 				   		GList *files,
10651 			           		gpointer callback_data)
10652 {
10653 	NemoView *view;
10654 
10655 	view = callback_data;
10656 
10657 	g_assert (NEMO_IS_VIEW (view));
10658 	g_assert (view->details->model == directory);
10659 	g_assert (view->details->metadata_for_files_in_directory_pending);
10660 
10661 	view->details->metadata_for_files_in_directory_pending = FALSE;
10662 
10663 	finish_loading_if_all_metadata_loaded (view);
10664 }
10665 
10666 static void
disconnect_handler(GObject * object,guint * id)10667 disconnect_handler (GObject *object, guint *id)
10668 {
10669 	if (*id != 0) {
10670 		g_signal_handler_disconnect (object, *id);
10671 		*id = 0;
10672 	}
10673 }
10674 
10675 static void
disconnect_directory_handler(NemoView * view,guint * id)10676 disconnect_directory_handler (NemoView *view, guint *id)
10677 {
10678 	disconnect_handler (G_OBJECT (view->details->model), id);
10679 }
10680 
10681 static void
disconnect_directory_as_file_handler(NemoView * view,guint * id)10682 disconnect_directory_as_file_handler (NemoView *view, guint *id)
10683 {
10684 	disconnect_handler (G_OBJECT (view->details->directory_as_file), id);
10685 }
10686 
10687 static void
disconnect_model_handlers(NemoView * view)10688 disconnect_model_handlers (NemoView *view)
10689 {
10690 	if (view->details->model == NULL) {
10691 		return;
10692 	}
10693 	disconnect_directory_handler (view, &view->details->files_added_handler_id);
10694 	disconnect_directory_handler (view, &view->details->files_changed_handler_id);
10695 	disconnect_directory_handler (view, &view->details->done_loading_handler_id);
10696 	disconnect_directory_handler (view, &view->details->load_error_handler_id);
10697 	disconnect_directory_as_file_handler (view, &view->details->file_changed_handler_id);
10698 	nemo_file_cancel_call_when_ready (view->details->directory_as_file,
10699 					      metadata_for_directory_as_file_ready_callback,
10700 					      view);
10701 	nemo_directory_cancel_callback (view->details->model,
10702 					    metadata_for_files_in_directory_ready_callback,
10703 					    view);
10704 	nemo_directory_file_monitor_remove (view->details->model,
10705 						&view->details->model);
10706 	nemo_file_monitor_remove (view->details->directory_as_file,
10707 				      &view->details->directory_as_file);
10708 }
10709 
10710 static void
nemo_view_select_file(NemoView * view,NemoFile * file)10711 nemo_view_select_file (NemoView *view, NemoFile *file)
10712 {
10713 	GList file_list;
10714 
10715 	file_list.data = file;
10716 	file_list.next = NULL;
10717 	file_list.prev = NULL;
10718 	nemo_view_call_set_selection (view, &file_list);
10719 }
10720 
10721 /**
10722  * nemo_view_stop_loading:
10723  *
10724  * Stop the current ongoing process, such as switching to a new uri.
10725  * @view: NemoView in question.
10726  *
10727  **/
10728 void
nemo_view_stop_loading(NemoView * view)10729 nemo_view_stop_loading (NemoView *view)
10730 {
10731 	g_return_if_fail (NEMO_IS_VIEW (view));
10732 
10733 	unschedule_display_of_pending_files (view);
10734 	reset_update_interval (view);
10735 
10736 	/* Free extra undisplayed files */
10737 	file_and_directory_list_free (view->details->new_added_files);
10738 	view->details->new_added_files = NULL;
10739 
10740 	file_and_directory_list_free (view->details->new_changed_files);
10741 	view->details->new_changed_files = NULL;
10742 
10743 	g_hash_table_remove_all (view->details->non_ready_files);
10744 
10745 	file_and_directory_list_free (view->details->old_added_files);
10746 	view->details->old_added_files = NULL;
10747 
10748 	file_and_directory_list_free (view->details->old_changed_files);
10749 	view->details->old_changed_files = NULL;
10750 
10751 	g_list_free_full (view->details->pending_selection, g_object_unref);
10752 	view->details->pending_selection = NULL;
10753 
10754 	if (view->details->model != NULL) {
10755 		nemo_directory_file_monitor_remove (view->details->model, view);
10756 	}
10757 	done_loading (view, FALSE);
10758 }
10759 
10760 gboolean
nemo_view_is_editable(NemoView * view)10761 nemo_view_is_editable (NemoView *view)
10762 {
10763 	NemoDirectory *directory;
10764 
10765 	directory = nemo_view_get_model (view);
10766 
10767 	if (directory != NULL) {
10768 		return nemo_directory_is_editable (directory);
10769 	}
10770 
10771 	return TRUE;
10772 }
10773 
10774 static gboolean
real_is_read_only(NemoView * view)10775 real_is_read_only (NemoView *view)
10776 {
10777 	NemoFile *file;
10778 
10779     if (showing_recent_directory (view)) {
10780         return TRUE;
10781     }
10782 
10783     if (showing_favorites_directory (view)) {
10784         return TRUE;
10785     }
10786 
10787 	if (!nemo_view_is_editable (view)) {
10788 		return TRUE;
10789 	}
10790 
10791     file = nemo_view_get_directory_as_file (view);
10792 
10793     if (file != NULL) {
10794         if (nemo_file_is_in_admin (file)) {
10795             return TRUE;
10796         }
10797 
10798         return !nemo_file_can_write (file);
10799     }
10800 
10801     return FALSE;
10802 }
10803 
10804 /**
10805  * nemo_view_should_show_file
10806  *
10807  * Returns whether or not this file should be displayed based on
10808  * current filtering options.
10809  */
10810 gboolean
nemo_view_should_show_file(NemoView * view,NemoFile * file)10811 nemo_view_should_show_file (NemoView *view, NemoFile *file)
10812 {
10813 	return nemo_file_should_show (file,
10814 					  view->details->show_hidden_files,
10815 					  view->details->show_foreign_files);
10816 }
10817 
10818 static gboolean
real_using_manual_layout(NemoView * view)10819 real_using_manual_layout (NemoView *view)
10820 {
10821 	g_return_val_if_fail (NEMO_IS_VIEW (view), FALSE);
10822 
10823 	return FALSE;
10824 }
10825 
10826 static void
schedule_update_menus_callback(gpointer callback_data)10827 schedule_update_menus_callback (gpointer callback_data)
10828 {
10829 	schedule_update_menus (NEMO_VIEW (callback_data));
10830 }
10831 
10832 void
nemo_view_ignore_hidden_file_preferences(NemoView * view)10833 nemo_view_ignore_hidden_file_preferences (NemoView *view)
10834 {
10835 	g_return_if_fail (view->details->model == NULL);
10836 
10837 	if (view->details->ignore_hidden_file_preferences) {
10838 		return;
10839 	}
10840 
10841 	view->details->show_hidden_files = FALSE;
10842 	view->details->ignore_hidden_file_preferences = TRUE;
10843 }
10844 
10845 void
nemo_view_set_show_foreign(NemoView * view,gboolean show_foreign)10846 nemo_view_set_show_foreign (NemoView *view,
10847 				gboolean show_foreign)
10848 {
10849 	view->details->show_foreign_files = show_foreign;
10850 }
10851 
10852 char *
nemo_view_get_uri(NemoView * view)10853 nemo_view_get_uri (NemoView *view)
10854 {
10855 	g_return_val_if_fail (NEMO_IS_VIEW (view), NULL);
10856 	if (view->details->model == NULL) {
10857 		return NULL;
10858 	}
10859 	return nemo_directory_get_uri (view->details->model);
10860 }
10861 
10862 void
nemo_view_move_copy_items(NemoView * view,const GList * item_uris,GArray * relative_item_points,const char * target_uri,int copy_action,int x,int y)10863 nemo_view_move_copy_items (NemoView *view,
10864 			       const GList *item_uris,
10865 			       GArray *relative_item_points,
10866 			       const char *target_uri,
10867 			       int copy_action,
10868 			       int x, int y)
10869 {
10870 	NemoFile *target_file;
10871 
10872 	g_assert (relative_item_points == NULL
10873 		  || relative_item_points->len == 0
10874 		  || g_list_length ((GList *)item_uris) == relative_item_points->len);
10875 
10876 	/* add the drop location to the icon offsets */
10877 	offset_drop_points (relative_item_points, x, y);
10878 
10879 	target_file = nemo_file_get_existing_by_uri (target_uri);
10880 	/* special-case "command:" here instead of starting a move/copy */
10881 	if (target_file != NULL && nemo_file_is_launcher (target_file)) {
10882 		nemo_file_unref (target_file);
10883 		nemo_launch_desktop_file (
10884 					      gtk_widget_get_screen (GTK_WIDGET (view)),
10885 					      target_uri, item_uris,
10886 					      nemo_view_get_containing_window (view));
10887 		return;
10888 	} else if (copy_action == GDK_ACTION_COPY &&
10889 		   nemo_is_file_roller_installed () &&
10890 		   target_file != NULL &&
10891 		   nemo_file_is_archive (target_file)) {
10892 		char *command, *quoted_uri, *unescaped, *tmp;
10893 		const GList *l;
10894 		GdkScreen  *screen;
10895 
10896 		/* Handle dropping onto a file-roller archiver file, instead of starting a move/copy */
10897 
10898 		nemo_file_unref (target_file);
10899 
10900         unescaped = g_uri_unescape_string (target_uri, "");
10901 		quoted_uri = g_shell_quote (unescaped);
10902 
10903 		command = g_strconcat ("file-roller -a ", quoted_uri, NULL);
10904 
10905         g_clear_pointer (&quoted_uri, g_free);
10906         g_clear_pointer (&unescaped, g_free);
10907 
10908 		for (l = item_uris; l != NULL; l = l->next) {
10909             unescaped = g_uri_unescape_string ((char *) l->data, "");
10910             quoted_uri = g_shell_quote (unescaped);
10911 
10912 			tmp = g_strconcat (command, " ", quoted_uri, NULL);
10913 			g_free (command);
10914 			command = tmp;
10915 
10916             g_clear_pointer (&quoted_uri, g_free);
10917             g_clear_pointer (&unescaped, g_free);
10918 		}
10919 
10920 		screen = gtk_widget_get_screen (GTK_WIDGET (view));
10921 		if (screen == NULL) {
10922 			screen = gdk_screen_get_default ();
10923 		}
10924 
10925 		nemo_launch_application_from_command (screen, command, FALSE, NULL);
10926 		g_free (command);
10927 
10928 		return;
10929 	}
10930 	nemo_file_unref (target_file);
10931 
10932 	nemo_file_operations_copy_move
10933 		(item_uris, relative_item_points,
10934 		 target_uri, copy_action, GTK_WIDGET (view),
10935 		 copy_move_done_callback, pre_copy_move (view));
10936 }
10937 
10938 static void
nemo_view_trash_state_changed_callback(NemoTrashMonitor * trash_monitor,gboolean state,gpointer callback_data)10939 nemo_view_trash_state_changed_callback (NemoTrashMonitor *trash_monitor,
10940 					    gboolean state, gpointer callback_data)
10941 {
10942 	NemoView *view;
10943 
10944 	view = (NemoView *) callback_data;
10945 	g_assert (NEMO_IS_VIEW (view));
10946 
10947 	schedule_update_menus (view);
10948 }
10949 
10950 void
nemo_view_start_batching_selection_changes(NemoView * view)10951 nemo_view_start_batching_selection_changes (NemoView *view)
10952 {
10953 	g_return_if_fail (NEMO_IS_VIEW (view));
10954 
10955 	++view->details->batching_selection_level;
10956 	view->details->selection_changed_while_batched = FALSE;
10957 }
10958 
10959 void
nemo_view_stop_batching_selection_changes(NemoView * view)10960 nemo_view_stop_batching_selection_changes (NemoView *view)
10961 {
10962 	g_return_if_fail (NEMO_IS_VIEW (view));
10963 	g_return_if_fail (view->details->batching_selection_level > 0);
10964 
10965 	if (--view->details->batching_selection_level == 0) {
10966 		if (view->details->selection_changed_while_batched) {
10967 			nemo_view_notify_selection_changed (view);
10968 		}
10969 	}
10970 }
10971 
10972 gboolean
nemo_view_get_active(NemoView * view)10973 nemo_view_get_active (NemoView *view)
10974 {
10975 	g_assert (NEMO_IS_VIEW (view));
10976 	return view->details->active;
10977 }
10978 
10979 static GArray *
real_get_selected_icon_locations(NemoView * view)10980 real_get_selected_icon_locations (NemoView *view)
10981 {
10982         /* By default, just return an empty list. */
10983         return g_array_new (FALSE, TRUE, sizeof (GdkPoint));
10984 }
10985 
10986 static void
nemo_view_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)10987 nemo_view_set_property (GObject         *object,
10988 			    guint            prop_id,
10989 			    const GValue    *value,
10990 			    GParamSpec      *pspec)
10991 {
10992 	NemoView *directory_view;
10993 	NemoWindowSlot *slot;
10994 	NemoWindow *window;
10995 
10996 	directory_view = NEMO_VIEW (object);
10997 
10998 	switch (prop_id)  {
10999 	case PROP_WINDOW_SLOT:
11000 		g_assert (directory_view->details->slot == NULL);
11001 
11002 		slot = NEMO_WINDOW_SLOT (g_value_get_object (value));
11003 		window = nemo_window_slot_get_window (slot);
11004 
11005 		directory_view->details->slot = slot;
11006 		directory_view->details->window = window;
11007 
11008 		g_signal_connect_object (directory_view->details->slot,
11009 					 "active", G_CALLBACK (slot_active),
11010 					 directory_view, 0);
11011 		g_signal_connect_object (directory_view->details->slot,
11012 					 "inactive", G_CALLBACK (slot_inactive),
11013 					 directory_view, 0);
11014 		g_signal_connect_object (directory_view->details->slot,
11015 					 "changed-pane", G_CALLBACK (slot_changed_pane),
11016 					 directory_view, 0);
11017 
11018 		g_signal_connect_object (directory_view->details->window,
11019 					 "hidden-files-mode-changed", G_CALLBACK (hidden_files_mode_changed),
11020 					 directory_view, 0);
11021 		nemo_view_init_show_hidden_files (directory_view);
11022 		break;
11023 	case PROP_SUPPORTS_ZOOMING:
11024 		directory_view->details->supports_zooming = g_value_get_boolean (value);
11025 		break;
11026 	default:
11027 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
11028 		break;
11029 	}
11030 }
11031 
11032 
11033 gboolean
nemo_view_handle_scroll_event(NemoView * directory_view,GdkEventScroll * event)11034 nemo_view_handle_scroll_event (NemoView *directory_view,
11035 				   GdkEventScroll *event)
11036 {
11037 	static gdouble total_delta_y = 0;
11038 	gdouble delta_x, delta_y;
11039 
11040 	if (event->state & GDK_CONTROL_MASK) {
11041 		switch (event->direction) {
11042 		case GDK_SCROLL_UP:
11043 			/* Zoom In */
11044 			nemo_view_bump_zoom_level (directory_view, 1);
11045 			return TRUE;
11046 
11047 		case GDK_SCROLL_DOWN:
11048 			/* Zoom Out */
11049 			nemo_view_bump_zoom_level (directory_view, -1);
11050 			return TRUE;
11051 
11052 		case GDK_SCROLL_SMOOTH:
11053 			gdk_event_get_scroll_deltas ((const GdkEvent *) event,
11054 						     &delta_x, &delta_y);
11055 
11056 			/* try to emulate a normal scrolling event by summing deltas */
11057 			total_delta_y += delta_y;
11058 
11059 			if (total_delta_y >= 1) {
11060 				total_delta_y = 0;
11061 				/* emulate scroll down */
11062 				nemo_view_bump_zoom_level (directory_view, -1);
11063 				return TRUE;
11064 			} else if (total_delta_y <= - 1) {
11065 				total_delta_y = 0;
11066 				/* emulate scroll up */
11067 				nemo_view_bump_zoom_level (directory_view, 1);
11068 				return TRUE;
11069 			} else {
11070 				/* eat event */
11071 				return TRUE;
11072 			}
11073 
11074 		case GDK_SCROLL_LEFT:
11075 		case GDK_SCROLL_RIGHT:
11076 			break;
11077 
11078 		default:
11079 			g_assert_not_reached ();
11080 		}
11081 	}
11082 
11083 	return FALSE;
11084 }
11085 
11086 /* handle Shift+Scroll, which will cause a zoom-in/out */
11087 static gboolean
nemo_view_scroll_event(GtkWidget * widget,GdkEventScroll * event)11088 nemo_view_scroll_event (GtkWidget *widget,
11089 			    GdkEventScroll *event)
11090 {
11091 	NemoView *directory_view;
11092 
11093 	directory_view = NEMO_VIEW (widget);
11094     if (!get_is_desktop_view (directory_view) &&
11095         nemo_view_handle_scroll_event (directory_view, event)) {
11096 		return TRUE;
11097 	}
11098 
11099 	return GTK_WIDGET_CLASS (parent_class)->scroll_event (widget, event);
11100 }
11101 
11102 
11103 static void
nemo_view_parent_set(GtkWidget * widget,GtkWidget * old_parent)11104 nemo_view_parent_set (GtkWidget *widget,
11105 			  GtkWidget *old_parent)
11106 {
11107 	NemoView *view;
11108 	GtkWidget *parent;
11109 
11110 	view = NEMO_VIEW (widget);
11111 
11112 	parent = gtk_widget_get_parent (widget);
11113 	g_assert (parent == NULL || old_parent == NULL);
11114 
11115 	if (GTK_WIDGET_CLASS (parent_class)->parent_set != NULL) {
11116 		GTK_WIDGET_CLASS (parent_class)->parent_set (widget, old_parent);
11117 	}
11118 
11119 	if (parent != NULL) {
11120 		g_assert (old_parent == NULL);
11121 
11122 		if (view->details->slot ==
11123 		    nemo_window_get_active_slot (view->details->window)) {
11124 			view->details->active = TRUE;
11125 
11126 			nemo_view_merge_menus (view);
11127 			schedule_update_menus (view);
11128 		}
11129 	} else {
11130 		nemo_view_unmerge_menus (view);
11131 		remove_update_menus_timeout_callback (view);
11132 	}
11133 }
11134 
11135 static void
nemo_view_class_init(NemoViewClass * klass)11136 nemo_view_class_init (NemoViewClass *klass)
11137 {
11138 	GObjectClass *oclass;
11139 	GtkWidgetClass *widget_class;
11140 	GtkScrolledWindowClass *scrolled_window_class;
11141 	GtkBindingSet *binding_set;
11142 
11143 	widget_class = GTK_WIDGET_CLASS (klass);
11144 	scrolled_window_class = GTK_SCROLLED_WINDOW_CLASS (klass);
11145 	oclass = G_OBJECT_CLASS (klass);
11146 
11147 	oclass->finalize = nemo_view_finalize;
11148 	oclass->set_property = nemo_view_set_property;
11149 
11150 	widget_class->destroy = nemo_view_destroy;
11151 	widget_class->scroll_event = nemo_view_scroll_event;
11152 	widget_class->parent_set = nemo_view_parent_set;
11153 
11154 	g_type_class_add_private (klass, sizeof (NemoViewDetails));
11155 
11156 	/* Get rid of the strange 3-pixel gap that GtkScrolledWindow
11157 	 * uses by default. It does us no good.
11158 	 */
11159 	scrolled_window_class->scrollbar_spacing = 0;
11160 
11161 	signals[ADD_FILE] =
11162 		g_signal_new ("add_file",
11163 		              G_TYPE_FROM_CLASS (klass),
11164 		              G_SIGNAL_RUN_LAST,
11165 		              G_STRUCT_OFFSET (NemoViewClass, add_file),
11166 		              NULL, NULL,
11167 		              g_cclosure_marshal_generic,
11168 		              G_TYPE_NONE, 2, NEMO_TYPE_FILE, NEMO_TYPE_DIRECTORY);
11169 	signals[BEGIN_FILE_CHANGES] =
11170 		g_signal_new ("begin_file_changes",
11171 		              G_TYPE_FROM_CLASS (klass),
11172 		              G_SIGNAL_RUN_LAST,
11173 		              G_STRUCT_OFFSET (NemoViewClass, begin_file_changes),
11174 		              NULL, NULL,
11175 		              g_cclosure_marshal_VOID__VOID,
11176 		              G_TYPE_NONE, 0);
11177 	signals[BEGIN_LOADING] =
11178 		g_signal_new ("begin_loading",
11179 		              G_TYPE_FROM_CLASS (klass),
11180 		              G_SIGNAL_RUN_LAST,
11181 		              G_STRUCT_OFFSET (NemoViewClass, begin_loading),
11182 		              NULL, NULL,
11183 		              g_cclosure_marshal_VOID__VOID,
11184 		              G_TYPE_NONE, 0);
11185 	signals[CLEAR] =
11186 		g_signal_new ("clear",
11187 		              G_TYPE_FROM_CLASS (klass),
11188 		              G_SIGNAL_RUN_LAST,
11189 		              G_STRUCT_OFFSET (NemoViewClass, clear),
11190 		              NULL, NULL,
11191 		              g_cclosure_marshal_VOID__VOID,
11192 		              G_TYPE_NONE, 0);
11193 	signals[END_FILE_CHANGES] =
11194 		g_signal_new ("end_file_changes",
11195 		              G_TYPE_FROM_CLASS (klass),
11196 		              G_SIGNAL_RUN_LAST,
11197 		              G_STRUCT_OFFSET (NemoViewClass, end_file_changes),
11198 		              NULL, NULL,
11199 		              g_cclosure_marshal_VOID__VOID,
11200 		              G_TYPE_NONE, 0);
11201 	signals[END_LOADING] =
11202 		g_signal_new ("end_loading",
11203 		              G_TYPE_FROM_CLASS (klass),
11204 		              G_SIGNAL_RUN_LAST,
11205 		              G_STRUCT_OFFSET (NemoViewClass, end_loading),
11206 		              NULL, NULL,
11207 		              g_cclosure_marshal_VOID__BOOLEAN,
11208 		              G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
11209 	signals[FILE_CHANGED] =
11210 		g_signal_new ("file_changed",
11211 		              G_TYPE_FROM_CLASS (klass),
11212 		              G_SIGNAL_RUN_LAST,
11213 		              G_STRUCT_OFFSET (NemoViewClass, file_changed),
11214 		              NULL, NULL,
11215 		              g_cclosure_marshal_generic,
11216 		              G_TYPE_NONE, 2, NEMO_TYPE_FILE, NEMO_TYPE_DIRECTORY);
11217 	signals[LOAD_ERROR] =
11218 		g_signal_new ("load_error",
11219 		              G_TYPE_FROM_CLASS (klass),
11220 		              G_SIGNAL_RUN_LAST,
11221 		              G_STRUCT_OFFSET (NemoViewClass, load_error),
11222 		              NULL, NULL,
11223 		              g_cclosure_marshal_VOID__POINTER,
11224 		              G_TYPE_NONE, 1, G_TYPE_POINTER);
11225 	signals[REMOVE_FILE] =
11226 		g_signal_new ("remove_file",
11227 		              G_TYPE_FROM_CLASS (klass),
11228 		              G_SIGNAL_RUN_LAST,
11229 		              G_STRUCT_OFFSET (NemoViewClass, remove_file),
11230 		              NULL, NULL,
11231 		              g_cclosure_marshal_generic,
11232 		              G_TYPE_NONE, 2, NEMO_TYPE_FILE, NEMO_TYPE_DIRECTORY);
11233 	signals[ZOOM_LEVEL_CHANGED] =
11234 		g_signal_new ("zoom-level-changed",
11235 			      G_TYPE_FROM_CLASS (klass),
11236 			      G_SIGNAL_RUN_LAST,
11237 			      0, NULL, NULL,
11238 			      g_cclosure_marshal_VOID__VOID,
11239 			      G_TYPE_NONE, 0);
11240 	signals[SELECTION_CHANGED] =
11241 		g_signal_new ("selection-changed",
11242 			      G_TYPE_FROM_CLASS (klass),
11243 			      G_SIGNAL_RUN_LAST,
11244 			      0,
11245 			      NULL, NULL,
11246 			      g_cclosure_marshal_VOID__VOID,
11247 			      G_TYPE_NONE, 0);
11248 	signals[TRASH] =
11249 		g_signal_new ("trash",
11250 			      G_TYPE_FROM_CLASS (klass),
11251 			      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
11252 			      G_STRUCT_OFFSET (NemoViewClass, trash),
11253 			      g_signal_accumulator_true_handled, NULL,
11254 			      g_cclosure_marshal_generic,
11255 			      G_TYPE_BOOLEAN, 0);
11256 	signals[DELETE] =
11257 		g_signal_new ("delete",
11258 			      G_TYPE_FROM_CLASS (klass),
11259 			      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
11260 			      G_STRUCT_OFFSET (NemoViewClass, delete),
11261 			      g_signal_accumulator_true_handled, NULL,
11262 			      g_cclosure_marshal_generic,
11263 			      G_TYPE_BOOLEAN, 0);
11264 
11265 	klass->get_selected_icon_locations = real_get_selected_icon_locations;
11266 	klass->is_read_only = real_is_read_only;
11267 	klass->load_error = real_load_error;
11268 	klass->can_rename_file = can_rename_file;
11269 	klass->start_renaming_file = start_renaming_file;
11270 	klass->get_backing_uri = real_get_backing_uri;
11271 	klass->using_manual_layout = real_using_manual_layout;
11272         klass->merge_menus = real_merge_menus;
11273         klass->unmerge_menus = real_unmerge_menus;
11274         klass->update_menus = real_update_menus;
11275 	klass->trash = real_trash;
11276 	klass->delete = real_delete;
11277 
11278 	copied_files_atom = gdk_atom_intern ("x-special/gnome-copied-files", FALSE);
11279 
11280 	properties[PROP_WINDOW_SLOT] =
11281 		g_param_spec_object ("window-slot",
11282 				     "Window Slot",
11283 				     "The parent window slot reference",
11284 				     NEMO_TYPE_WINDOW_SLOT,
11285 				     G_PARAM_WRITABLE |
11286 				     G_PARAM_CONSTRUCT_ONLY);
11287 	properties[PROP_SUPPORTS_ZOOMING] =
11288 		g_param_spec_boolean ("supports-zooming",
11289 				      "Supports zooming",
11290 				      "Whether the view supports zooming",
11291 				      TRUE,
11292 				      G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
11293 				      G_PARAM_STATIC_STRINGS);
11294 
11295 	g_object_class_install_properties (oclass, NUM_PROPERTIES, properties);
11296 
11297 	binding_set = gtk_binding_set_by_class (klass);
11298 
11299     gboolean swap_keys = g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_SWAP_TRASH_DELETE);
11300 
11301     if (swap_keys) {
11302         gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, 0,
11303                           "delete", 0);
11304         gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, 0,
11305                           "delete", 0);
11306         gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, GDK_SHIFT_MASK,
11307                           "trash", 0);
11308         gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, GDK_SHIFT_MASK,
11309                           "trash", 0);
11310     } else {
11311         gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, 0,
11312                           "trash", 0);
11313         gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, 0,
11314                           "trash", 0);
11315         gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, GDK_SHIFT_MASK,
11316                           "delete", 0);
11317         gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, GDK_SHIFT_MASK,
11318                           "delete", 0);
11319     }
11320 }
11321