1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 
3 /* fm-icon-view.c - implementation of icon view of directory.
4 
5    Copyright (C) 2000, 2001 Eazel, Inc.
6 
7    The Gnome Library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Library General Public License as
9    published by the Free Software Foundation; either version 2 of the
10    License, or (at your option) any later version.
11 
12    The Gnome Library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Library General Public License for more details.
16 
17    You should have received a copy of the GNU Library General Public
18    License along with the Gnome Library; see the file COPYING.LIB.  If not,
19    write to the Free Software Foundation, Inc., 51 Franklin Street - Suite 500,
20    Boston, MA 02110-1335, USA.
21 
22    Authors: John Sullivan <sullivan@eazel.com>
23 */
24 
25 #include <config.h>
26 
27 #include "nemo-icon-view.h"
28 
29 #include "nemo-actions.h"
30 #include "nemo-icon-view-container.h"
31 #include "nemo-icon-view-grid-container.h"
32 #include "nemo-error-reporting.h"
33 #include "nemo-view-dnd.h"
34 #include "nemo-view-factory.h"
35 #include "nemo-window.h"
36 #include "nemo-desktop-window.h"
37 #include "nemo-desktop-manager.h"
38 #include "nemo-application.h"
39 
40 #include <stdlib.h>
41 #include <eel/eel-vfs-extensions.h>
42 #include <errno.h>
43 #include <fcntl.h>
44 #include <gtk/gtk.h>
45 #include <glib/gi18n.h>
46 #include <gio/gio.h>
47 #include <libnemo-private/nemo-clipboard-monitor.h>
48 #include <libnemo-private/nemo-directory.h>
49 #include <libnemo-private/nemo-dnd.h>
50 #include <libnemo-private/nemo-file-dnd.h>
51 #include <libnemo-private/nemo-file-utilities.h>
52 #include <libnemo-private/nemo-ui-utilities.h>
53 #include <libnemo-private/nemo-global-preferences.h>
54 #include <libnemo-private/nemo-icon-container.h>
55 #include <libnemo-private/nemo-icon-dnd.h>
56 #include <libnemo-private/nemo-icon.h>
57 #include <libnemo-private/nemo-link.h>
58 #include <libnemo-private/nemo-metadata.h>
59 #include <libnemo-private/nemo-clipboard.h>
60 #include <libnemo-private/nemo-desktop-icon-file.h>
61 #include <libnemo-private/nemo-desktop-utils.h>
62 #include <libnemo-private/nemo-desktop-directory.h>
63 
64 #define DEBUG_FLAG NEMO_DEBUG_ICON_VIEW
65 #include <libnemo-private/nemo-debug.h>
66 
67 #include <locale.h>
68 #include <signal.h>
69 #include <stdio.h>
70 #include <sys/types.h>
71 #include <sys/wait.h>
72 #include <unistd.h>
73 
74 #define POPUP_PATH_ICON_APPEARANCE		"/selection/Icon Appearance Items"
75 
76 enum
77 {
78 	PROP_COMPACT = 1,
79 	PROP_SUPPORTS_AUTO_LAYOUT,
80 	PROP_IS_DESKTOP,
81 	PROP_SUPPORTS_KEEP_ALIGNED,
82 	PROP_SUPPORTS_LABELS_BESIDE_ICONS,
83 	NUM_PROPERTIES
84 };
85 
86 static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
87 
88 typedef struct {
89 	const NemoFileSortType sort_type;
90 	const char *metadata_text;
91 	const char *action;
92 	const char *menu_label;
93 	const char *menu_hint;
94 } SortCriterion;
95 
96 typedef enum {
97 	MENU_ITEM_TYPE_STANDARD,
98 	MENU_ITEM_TYPE_CHECK,
99 	MENU_ITEM_TYPE_RADIO,
100 	MENU_ITEM_TYPE_TREE
101 } MenuItemType;
102 
103 struct NemoIconViewDetails
104 {
105 	GList *icons_not_positioned;
106 
107 	guint react_to_icon_change_idle_id;
108 
109 	const SortCriterion *sort;
110 	gboolean sort_reversed;
111 
112 	GtkActionGroup *icon_action_group;
113 	guint icon_merge_id;
114 
115 	gboolean compact;
116 
117 	gulong clipboard_handler_id;
118 
119 	GtkWidget *icon_container;
120 
121 	gboolean supports_auto_layout;
122 	gboolean is_desktop;
123 	gboolean supports_keep_aligned;
124 	gboolean supports_labels_beside_icons;
125 };
126 
127 
128 /* Note that the first item in this list is the default sort,
129  * and that the items show up in the menu in the order they
130  * appear in this list.
131  */
132 static const SortCriterion sort_criteria[] = {
133 	{
134 		NEMO_FILE_SORT_BY_DISPLAY_NAME,
135 		"name",
136 		"Sort by Name",
137 		N_("by _Name"),
138 		N_("Keep icons sorted by name in rows")
139 	},
140 	{
141 		NEMO_FILE_SORT_BY_SIZE,
142 		"size",
143 		"Sort by Size",
144 		N_("by _Size"),
145 		N_("Keep icons sorted by size in rows")
146 	},
147 	{
148 		NEMO_FILE_SORT_BY_TYPE,
149 		"type",
150 		"Sort by Type",
151 		N_("by _Type"),
152 		N_("Keep icons sorted by type in rows")
153 	},
154     {
155         NEMO_FILE_SORT_BY_DETAILED_TYPE,
156         "detailed_type",
157         "Sort by Detailed Type",
158         N_("by _Detailed Type"),
159         N_("Keep icons sorted by detailed type in rows")
160     },
161 	{
162 		NEMO_FILE_SORT_BY_MTIME,
163 		"modification date",
164 		"Sort by Modification Date",
165 		N_("by Modification _Date"),
166 		N_("Keep icons sorted by modification date in rows")
167 	},
168 	{
169 		NEMO_FILE_SORT_BY_TRASHED_TIME,
170 		"trashed",
171 		"Sort by Trash Time",
172 		N_("by T_rash Time"),
173 		N_("Keep icons sorted by trash time in rows")
174 	}
175 };
176 
177 static void                 nemo_icon_view_set_directory_sort_by        (NemoIconView           *icon_view,
178 									     NemoFile         *file,
179 									     const char           *sort_by);
180 static void                 nemo_icon_view_set_zoom_level               (NemoIconView           *view,
181 									     NemoZoomLevel     new_level,
182 									     gboolean              always_emit);
183 static void                 nemo_icon_view_update_click_mode            (NemoIconView           *icon_view);
184 static void                 nemo_icon_view_update_click_to_rename_mode  (NemoIconView           *icon_view);
185 static gboolean             nemo_icon_view_is_desktop      (NemoIconView           *icon_view);
186 static void                 nemo_icon_view_reveal_selection       (NemoView               *view);
187 static const SortCriterion *get_sort_criterion_by_sort_type           (NemoFileSortType  sort_type);
188 static void                 switch_to_manual_layout                   (NemoIconView     *view);
189 static void                 update_layout_menus                       (NemoIconView     *view);
190 static NemoFileSortType get_default_sort_order                    (NemoFile         *file,
191 								       gboolean             *reversed);
192 static void                 nemo_icon_view_clear_full                 (NemoView *view,
193                                                                        gboolean  destroying);
194 static const SortCriterion *get_sort_criterion_by_metadata_text (const char *metadata_text);
195 static void		    nemo_icon_view_remove_file (NemoView *view, NemoFile *file, NemoDirectory *directory);
196 
197 G_DEFINE_TYPE (NemoIconView, nemo_icon_view, NEMO_TYPE_VIEW);
198 
199 static void
nemo_icon_view_destroy(GtkWidget * object)200 nemo_icon_view_destroy (GtkWidget *object)
201 {
202 	NemoIconView *icon_view;
203 
204 	icon_view = NEMO_ICON_VIEW (object);
205 
206 	nemo_icon_view_clear_full (NEMO_VIEW (object), TRUE);
207 
208         if (icon_view->details->react_to_icon_change_idle_id != 0) {
209                 g_source_remove (icon_view->details->react_to_icon_change_idle_id);
210 		icon_view->details->react_to_icon_change_idle_id = 0;
211         }
212 
213 	if (icon_view->details->clipboard_handler_id != 0) {
214 		g_signal_handler_disconnect (nemo_clipboard_monitor_get (),
215 					     icon_view->details->clipboard_handler_id);
216 		icon_view->details->clipboard_handler_id = 0;
217 	}
218 
219 	if (icon_view->details->icons_not_positioned) {
220 		nemo_file_list_free (icon_view->details->icons_not_positioned);
221 		icon_view->details->icons_not_positioned = NULL;
222 	}
223 
224 	GTK_WIDGET_CLASS (nemo_icon_view_parent_class)->destroy (object);
225 }
226 
227 static void
sync_directory_monitor_number(NemoIconView * view,NemoFile * file)228 sync_directory_monitor_number (NemoIconView *view, NemoFile *file)
229 {
230     NemoDirectory *directory;
231     NemoDesktopWindow *desktop_window;
232     gint monitor;
233 
234     if (!view->details->is_desktop) {
235         return;
236     }
237 
238     desktop_window = NEMO_DESKTOP_WINDOW (nemo_view_get_nemo_window (NEMO_VIEW (view)));
239 
240     monitor = nemo_desktop_window_get_monitor (desktop_window);
241 
242     directory = nemo_view_get_model (NEMO_VIEW (view));
243 
244     NEMO_DESKTOP_DIRECTORY (directory)->display_number = monitor;
245 }
246 
247 
248 static NemoIconContainer *
get_icon_container(NemoIconView * icon_view)249 get_icon_container (NemoIconView *icon_view)
250 {
251 	return NEMO_ICON_CONTAINER (icon_view->details->icon_container);
252 }
253 
254 NemoIconContainer *
nemo_icon_view_get_icon_container(NemoIconView * icon_view)255 nemo_icon_view_get_icon_container (NemoIconView *icon_view)
256 {
257 	return get_icon_container (icon_view);
258 }
259 
260 static gboolean
nemo_icon_view_supports_manual_layout(NemoIconView * view)261 nemo_icon_view_supports_manual_layout (NemoIconView *view)
262 {
263 	g_return_val_if_fail (NEMO_IS_ICON_VIEW (view), FALSE);
264 
265 	return !nemo_icon_view_is_compact (view);
266 }
267 
268 static void
real_set_sort_criterion(NemoIconView * icon_view,const SortCriterion * sort,gboolean clear,gboolean set_metadata)269 real_set_sort_criterion (NemoIconView *icon_view,
270                          const SortCriterion *sort,
271                          gboolean clear,
272 			 gboolean set_metadata)
273 {
274 	NemoFile *file;
275 
276 	file = nemo_view_get_directory_as_file (NEMO_VIEW (icon_view));
277 
278     sync_directory_monitor_number (icon_view, file);
279 
280 	if (clear) {
281 		nemo_file_set_metadata (file,
282                                 NEMO_METADATA_KEY_ICON_VIEW_SORT_BY,
283                                 NULL,
284                                 NULL);
285 		nemo_file_set_metadata (file,
286                                 NEMO_METADATA_KEY_ICON_VIEW_SORT_REVERSED,
287                                 NULL,
288                                 NULL);
289         icon_view->details->sort =
290             get_sort_criterion_by_sort_type (get_default_sort_order (file, &icon_view->details->sort_reversed));
291     } else if (set_metadata) {
292 		/* Store the new sort setting. */
293         nemo_icon_view_set_directory_sort_by (icon_view,
294                                               file,
295                                               sort->metadata_text);
296     }
297 
298 	/* Update the layout menus to match the new sort setting. */
299 	update_layout_menus (icon_view);
300 }
301 
302 static void
set_sort_criterion(NemoIconView * icon_view,const SortCriterion * sort,gboolean set_metadata)303 set_sort_criterion (NemoIconView *icon_view,
304 		    const SortCriterion *sort,
305 		    gboolean set_metadata)
306 {
307 	if (sort == NULL ||
308 	    icon_view->details->sort == sort) {
309 		return;
310 	}
311 
312 	icon_view->details->sort = sort;
313 
314         real_set_sort_criterion (icon_view, sort, FALSE, set_metadata);
315 }
316 
317 static void
clear_sort_criterion(NemoIconView * icon_view)318 clear_sort_criterion (NemoIconView *icon_view)
319 {
320 	real_set_sort_criterion (icon_view, NULL, TRUE, TRUE);
321 }
322 
323 static void
nemo_icon_view_clean_up(NemoIconView * icon_view)324 nemo_icon_view_clean_up (NemoIconView *icon_view)
325 {
326 	NemoIconContainer *icon_container;
327 	gboolean saved_sort_reversed;
328 
329 	icon_container = get_icon_container (icon_view);
330 
331 	/* Hardwire Clean Up to always be by name, in forward order */
332 	saved_sort_reversed = icon_view->details->sort_reversed;
333 
334 	nemo_icon_view_set_sort_reversed (icon_view, FALSE, FALSE);
335 	set_sort_criterion (icon_view, &sort_criteria[0], FALSE);
336 
337 	nemo_icon_container_sort (icon_container);
338 	nemo_icon_container_freeze_icon_positions (icon_container);
339 
340 	nemo_icon_view_set_sort_reversed (icon_view, saved_sort_reversed, FALSE);
341 }
342 
343 static void
action_clean_up_callback(GtkAction * action,gpointer callback_data)344 action_clean_up_callback (GtkAction *action, gpointer callback_data)
345 {
346 	nemo_icon_view_clean_up (NEMO_ICON_VIEW (callback_data));
347 }
348 
349 static gboolean
nemo_icon_view_using_auto_layout(NemoIconView * icon_view)350 nemo_icon_view_using_auto_layout (NemoIconView *icon_view)
351 {
352 	return nemo_icon_container_is_auto_layout
353 		(get_icon_container (icon_view));
354 }
355 
356 static void
action_sort_radio_callback(GtkAction * action,GtkRadioAction * current,NemoIconView * view)357 action_sort_radio_callback (GtkAction *action,
358 			    GtkRadioAction *current,
359 			    NemoIconView *view)
360 {
361 	NemoFileSortType sort_type;
362 
363 	sort_type = gtk_radio_action_get_current_value (current);
364 
365 	/* Note that id might be a toggle item.
366 	 * Ignore non-sort ids so that they don't cause sorting.
367 	 */
368 	if (sort_type == NEMO_FILE_SORT_NONE) {
369 		switch_to_manual_layout (view);
370 	} else {
371 		nemo_icon_view_set_sort_criterion_by_sort_type (view, sort_type);
372 	}
373 }
374 
375 static void
list_covers(NemoIconData * data,gpointer callback_data)376 list_covers (NemoIconData *data, gpointer callback_data)
377 {
378 	GSList **file_list;
379 
380 	file_list = callback_data;
381 
382 	*file_list = g_slist_prepend (*file_list, data);
383 }
384 
385 static void
unref_cover(NemoIconData * data,gpointer callback_data)386 unref_cover (NemoIconData *data, gpointer callback_data)
387 {
388 	nemo_file_unref (NEMO_FILE (data));
389 }
390 
391 static void
nemo_icon_view_clear_full(NemoView * view,gboolean destroying)392 nemo_icon_view_clear_full (NemoView *view, gboolean destroying)
393 {
394 	NemoIconContainer *icon_container;
395 	GSList *file_list;
396 
397 	g_return_if_fail (NEMO_IS_ICON_VIEW (view));
398 
399 	icon_container = get_icon_container (NEMO_ICON_VIEW (view));
400 	if (!icon_container)
401 		return;
402 
403 	/* Clear away the existing icons. */
404 	file_list = NULL;
405 	nemo_icon_container_for_each (icon_container, list_covers, &file_list);
406 	nemo_icon_container_clear (icon_container);
407 
408     if (!destroying) {
409         nemo_icon_container_update_scroll_region (icon_container);
410     }
411 
412 	g_slist_foreach (file_list, (GFunc)unref_cover, NULL);
413 	g_slist_free (file_list);
414 }
415 
416 static void
nemo_icon_view_clear(NemoView * view)417 nemo_icon_view_clear (NemoView *view)
418 {
419     nemo_icon_view_clear_full (view, FALSE);
420 }
421 
422 static gboolean
should_show_file_on_screen(NemoView * view,NemoFile * file)423 should_show_file_on_screen (NemoView *view, NemoFile *file)
424 {
425 	if (!nemo_view_should_show_file (view, file)) {
426 		return FALSE;
427 	}
428 
429 	return TRUE;
430 }
431 
432 static void
nemo_icon_view_remove_file(NemoView * view,NemoFile * file,NemoDirectory * directory)433 nemo_icon_view_remove_file (NemoView *view, NemoFile *file, NemoDirectory *directory)
434 {
435 	NemoIconView *icon_view;
436 
437 	/* This used to assert that 'directory == nemo_view_get_model (view)', but that
438 	 * resulted in a lot of crash reports (bug #352592). I don't see how that trace happens.
439 	 * It seems that somehow we get a files_changed event sent to the view from a directory
440 	 * that isn't the model, but the code disables the monitor and signal callback handlers when
441 	 * changing directories. Maybe we can get some more information when this happens.
442 	 * Further discussion in bug #368178.
443 	 */
444 	if (directory != nemo_view_get_model (view)) {
445 		char *file_uri, *dir_uri, *model_uri;
446 		file_uri = nemo_file_get_uri (file);
447 		dir_uri = nemo_directory_get_uri (directory);
448 		model_uri = nemo_directory_get_uri (nemo_view_get_model (view));
449 		g_warning ("nemo_icon_view_remove_file() - directory not icon view model, shouldn't happen.\n"
450 			   "file: %p:%s, dir: %p:%s, model: %p:%s, view loading: %d\n"
451 			   "If you see this, please add this info to http://bugzilla.gnome.org/show_bug.cgi?id=368178",
452 			   file, file_uri, directory, dir_uri, nemo_view_get_model (view), model_uri, nemo_view_get_loading (view));
453 		g_free (file_uri);
454 		g_free (dir_uri);
455 		g_free (model_uri);
456 	}
457 
458 	icon_view = NEMO_ICON_VIEW (view);
459 
460 	if (nemo_icon_container_remove (get_icon_container (icon_view),
461 					    NEMO_ICON_CONTAINER_ICON_DATA (file))) {
462 		nemo_file_unref (file);
463 	}
464 }
465 
466 static void
nemo_icon_view_add_file(NemoView * view,NemoFile * file,NemoDirectory * directory)467 nemo_icon_view_add_file (NemoView *view, NemoFile *file, NemoDirectory *directory)
468 {
469 	NemoIconView *icon_view;
470 	NemoIconContainer *icon_container;
471 
472 	g_assert (directory == nemo_view_get_model (view));
473 
474 	icon_view = NEMO_ICON_VIEW (view);
475 
476     if (icon_view->details->is_desktop &&
477         !should_show_file_on_screen (view, file)) {
478         return;
479     }
480 
481     icon_container = get_icon_container (icon_view);
482 
483     if (nemo_file_has_thumbnail_access_problem (file)) {
484         nemo_application_set_cache_flag (nemo_application_get_singleton ());
485         nemo_window_slot_check_bad_cache_bar (nemo_view_get_nemo_window_slot (view));
486     }
487 
488 	/* Reset scroll region for the first icon added when loading a directory. */
489 	if (nemo_view_get_loading (view) && nemo_icon_container_is_empty (icon_container)) {
490 		nemo_icon_container_reset_scroll_region (icon_container);
491 	}
492 
493 	if (nemo_icon_container_add (icon_container,
494 					 NEMO_ICON_CONTAINER_ICON_DATA (file))) {
495 		nemo_file_ref (file);
496 	}
497 }
498 
499 static void
nemo_icon_view_file_changed(NemoView * view,NemoFile * file,NemoDirectory * directory)500 nemo_icon_view_file_changed (NemoView *view, NemoFile *file, NemoDirectory *directory)
501 {
502 	NemoIconView *icon_view;
503 
504 	g_assert (directory == nemo_view_get_model (view));
505 
506 	g_return_if_fail (view != NULL);
507 	icon_view = NEMO_ICON_VIEW (view);
508 
509 	if (!icon_view->details->is_desktop) {
510 		nemo_icon_container_request_update
511 			(get_icon_container (icon_view),
512 			 NEMO_ICON_CONTAINER_ICON_DATA (file));
513 		return;
514 	}
515 
516 	if (!should_show_file_on_screen (view, file)) {
517 		nemo_icon_view_remove_file (view, file, directory);
518 	} else {
519 
520 		nemo_icon_container_request_update
521 			(get_icon_container (icon_view),
522 			 NEMO_ICON_CONTAINER_ICON_DATA (file));
523 	}
524 }
525 
526 static gboolean
nemo_icon_view_supports_auto_layout(NemoIconView * view)527 nemo_icon_view_supports_auto_layout (NemoIconView *view)
528 {
529 	g_return_val_if_fail (NEMO_IS_ICON_VIEW (view), FALSE);
530 
531 	return view->details->supports_auto_layout;
532 }
533 
534 static gboolean
nemo_icon_view_is_desktop(NemoIconView * view)535 nemo_icon_view_is_desktop (NemoIconView *view)
536 {
537 	g_return_val_if_fail (NEMO_IS_ICON_VIEW (view), FALSE);
538 
539 	return view->details->is_desktop;
540 }
541 
542 static gboolean
nemo_icon_view_supports_keep_aligned(NemoIconView * view)543 nemo_icon_view_supports_keep_aligned (NemoIconView *view)
544 {
545 	g_return_val_if_fail (NEMO_IS_ICON_VIEW (view), FALSE);
546 
547 	return view->details->supports_keep_aligned;
548 }
549 
550 static gboolean
nemo_icon_view_supports_labels_beside_icons(NemoIconView * view)551 nemo_icon_view_supports_labels_beside_icons (NemoIconView *view)
552 {
553 	g_return_val_if_fail (NEMO_IS_ICON_VIEW (view), FALSE);
554 
555 	return view->details->supports_labels_beside_icons;
556 }
557 
558 static void
update_layout_menus(NemoIconView * view)559 update_layout_menus (NemoIconView *view)
560 {
561 	gboolean is_auto_layout;
562 	GtkAction *action;
563 	const char *action_name;
564 	NemoFile *file;
565 
566 	if (view->details->icon_action_group == NULL) {
567 		return;
568 	}
569 
570 	is_auto_layout = nemo_icon_view_using_auto_layout (view);
571 	file = nemo_view_get_directory_as_file (NEMO_VIEW (view));
572 
573 	if (nemo_icon_view_supports_auto_layout (view)) {
574 		/* Mark sort criterion. */
575 		action_name = is_auto_layout ? view->details->sort->action : NEMO_ACTION_MANUAL_LAYOUT;
576 		action = gtk_action_group_get_action (view->details->icon_action_group,
577 						      action_name);
578 		gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
579 
580         action = gtk_action_group_get_action (view->details->icon_action_group,
581                                               NEMO_ACTION_REVERSED_ORDER);
582 		gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
583 					      view->details->sort_reversed);
584 		gtk_action_set_sensitive (action, is_auto_layout);
585 
586 		action = gtk_action_group_get_action (view->details->icon_action_group,
587 		                                      NEMO_ACTION_SORT_TRASH_TIME);
588 
589 		if (file != NULL && nemo_file_is_in_trash (file)) {
590 			gtk_action_set_visible (action, TRUE);
591 		} else {
592 			gtk_action_set_visible (action, FALSE);
593 		}
594 	}
595 
596 	action = gtk_action_group_get_action (view->details->icon_action_group,
597 					      NEMO_ACTION_MANUAL_LAYOUT);
598 	gtk_action_set_visible (action,
599 				nemo_icon_view_supports_manual_layout (view));
600 
601 	/* Clean Up is only relevant for manual layout */
602 	action = gtk_action_group_get_action (view->details->icon_action_group,
603 					      NEMO_ACTION_CLEAN_UP);
604 	gtk_action_set_sensitive (action, !is_auto_layout);
605 
606 	if (nemo_icon_view_is_desktop (view)) {
607 		gtk_action_set_label (action, _("_Organize Desktop by Name"));
608 	}
609 
610 	action = gtk_action_group_get_action (view->details->icon_action_group,
611 					      NEMO_ACTION_KEEP_ALIGNED);
612 	gtk_action_set_visible (action,
613 				nemo_icon_view_supports_keep_aligned (view));
614 	gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
615 				      nemo_icon_container_is_keep_aligned (get_icon_container (view)));
616 	gtk_action_set_sensitive (action, !is_auto_layout);
617 }
618 
619 
620 gchar *
nemo_icon_view_get_directory_sort_by(NemoIconView * icon_view,NemoFile * file)621 nemo_icon_view_get_directory_sort_by (NemoIconView *icon_view,
622 					  NemoFile *file)
623 {
624 	const SortCriterion *default_sort_criterion;
625 
626 	if (!nemo_icon_view_supports_auto_layout (icon_view)) {
627 		return g_strdup ("name");
628 	}
629 
630 	default_sort_criterion = get_sort_criterion_by_sort_type (get_default_sort_order (file, NULL));
631 	g_return_val_if_fail (default_sort_criterion != NULL, NULL);
632 
633     sync_directory_monitor_number (icon_view, file);
634 
635     return nemo_file_get_metadata (file,
636                                    NEMO_METADATA_KEY_ICON_VIEW_SORT_BY,
637                                    default_sort_criterion->metadata_text);
638 }
639 
640 static NemoFileSortType
get_default_sort_order(NemoFile * file,gboolean * reversed)641 get_default_sort_order (NemoFile *file, gboolean *reversed)
642 {
643 	NemoFileSortType retval, default_sort_order;
644 	gboolean default_sort_in_reverse_order;
645 
646 	default_sort_order = g_settings_get_enum (nemo_preferences,
647 						  NEMO_PREFERENCES_DEFAULT_SORT_ORDER);
648 	default_sort_in_reverse_order = g_settings_get_boolean (nemo_preferences,
649 								NEMO_PREFERENCES_DEFAULT_SORT_IN_REVERSE_ORDER);
650 
651 	retval = nemo_file_get_default_sort_type (file, reversed);
652 
653 	if (retval == NEMO_FILE_SORT_NONE) {
654 
655 		if (reversed != NULL) {
656 			*reversed = default_sort_in_reverse_order;
657 		}
658 
659 		retval = CLAMP (default_sort_order, NEMO_FILE_SORT_BY_DISPLAY_NAME,
660 				NEMO_FILE_SORT_BY_MTIME);
661 	}
662 
663 	return retval;
664 }
665 
666 static void
nemo_icon_view_set_directory_sort_by(NemoIconView * icon_view,NemoFile * file,const char * sort_by)667 nemo_icon_view_set_directory_sort_by (NemoIconView *icon_view,
668 					  NemoFile *file,
669 					  const char *sort_by)
670 {
671 	const SortCriterion *default_sort_criterion;
672 
673 	if (!nemo_icon_view_supports_auto_layout (icon_view)) {
674 		return;
675 	}
676 
677 	default_sort_criterion = get_sort_criterion_by_sort_type (get_default_sort_order (file, NULL));
678 	g_return_if_fail (default_sort_criterion != NULL);
679 
680     sync_directory_monitor_number (icon_view, file);
681 
682     nemo_file_set_metadata (file,
683                             NEMO_METADATA_KEY_ICON_VIEW_SORT_BY,
684                             default_sort_criterion->metadata_text,
685                             sort_by);
686 }
687 
688 gboolean
nemo_icon_view_get_directory_sort_reversed(NemoIconView * icon_view,NemoFile * file)689 nemo_icon_view_get_directory_sort_reversed (NemoIconView *icon_view,
690 						NemoFile *file)
691 {
692 	gboolean reversed;
693 
694 	if (!nemo_icon_view_supports_auto_layout (icon_view)) {
695 		return FALSE;
696 	}
697 
698 	get_default_sort_order (file, &reversed);
699 
700     sync_directory_monitor_number (icon_view, file);
701 
702     return nemo_file_get_boolean_metadata (file,
703                                            NEMO_METADATA_KEY_ICON_VIEW_SORT_REVERSED,
704                                            reversed);
705 }
706 
707 static void
nemo_icon_view_set_directory_sort_reversed(NemoIconView * icon_view,NemoFile * file,gboolean sort_reversed)708 nemo_icon_view_set_directory_sort_reversed (NemoIconView *icon_view,
709 						NemoFile *file,
710 						gboolean sort_reversed)
711 {
712 	gboolean reversed;
713 
714 	if (!nemo_icon_view_supports_auto_layout (icon_view)) {
715 		return;
716 	}
717 
718 	get_default_sort_order (file, &reversed);
719 
720     sync_directory_monitor_number (icon_view, file);
721 
722     nemo_file_set_boolean_metadata (file,
723                                     NEMO_METADATA_KEY_ICON_VIEW_SORT_REVERSED,
724                                     reversed,
725                                     sort_reversed);
726 }
727 
728 static gboolean
get_default_directory_keep_aligned(void)729 get_default_directory_keep_aligned (void)
730 {
731 	return TRUE;
732 }
733 
734 static gboolean
nemo_icon_view_get_directory_keep_aligned(NemoIconView * icon_view,NemoFile * file)735 nemo_icon_view_get_directory_keep_aligned (NemoIconView *icon_view,
736 					       NemoFile *file)
737 {
738 	if (!nemo_icon_view_supports_keep_aligned (icon_view)) {
739 		return FALSE;
740 	}
741 
742     sync_directory_monitor_number (icon_view, file);
743 
744     return nemo_file_get_boolean_metadata (file,
745                                            NEMO_METADATA_KEY_ICON_VIEW_KEEP_ALIGNED,
746                                            get_default_directory_keep_aligned ());
747 }
748 
749 void
nemo_icon_view_set_directory_keep_aligned(NemoIconView * icon_view,NemoFile * file,gboolean keep_aligned)750 nemo_icon_view_set_directory_keep_aligned (NemoIconView *icon_view,
751 					       NemoFile *file,
752 					       gboolean keep_aligned)
753 {
754 	if (!nemo_icon_view_supports_keep_aligned (icon_view)) {
755 		return;
756 	}
757 
758     sync_directory_monitor_number (icon_view, file);
759 
760     nemo_file_set_boolean_metadata (file,
761                                     NEMO_METADATA_KEY_ICON_VIEW_KEEP_ALIGNED,
762                                     get_default_directory_keep_aligned (),
763                                     keep_aligned);
764 }
765 
766 static gboolean
nemo_icon_view_get_directory_auto_layout(NemoIconView * icon_view,NemoFile * file)767 nemo_icon_view_get_directory_auto_layout (NemoIconView *icon_view,
768 					      NemoFile *file)
769 {
770 	if (!nemo_icon_view_supports_auto_layout (icon_view)) {
771 		return FALSE;
772 	}
773 
774 	if (!nemo_icon_view_supports_manual_layout (icon_view)) {
775 		return TRUE;
776 	}
777 
778     sync_directory_monitor_number (icon_view, file);
779 
780     return nemo_file_get_boolean_metadata (file,
781                                            NEMO_METADATA_KEY_ICON_VIEW_AUTO_LAYOUT,
782                                            TRUE);
783 }
784 
785 static void
nemo_icon_view_set_directory_auto_layout(NemoIconView * icon_view,NemoFile * file,gboolean auto_layout)786 nemo_icon_view_set_directory_auto_layout (NemoIconView *icon_view,
787 					      NemoFile *file,
788 					gboolean auto_layout)
789 {
790 	if (!nemo_icon_view_supports_auto_layout (icon_view) ||
791 	    !nemo_icon_view_supports_manual_layout (icon_view)) {
792 		return;
793 	}
794 
795     sync_directory_monitor_number (icon_view, file);
796 
797     nemo_file_set_boolean_metadata (file,
798                                     NEMO_METADATA_KEY_ICON_VIEW_AUTO_LAYOUT,
799                                     TRUE,
800                                     auto_layout);
801 }
802 
803 void
nemo_icon_view_set_directory_horizontal_layout(NemoIconView * icon_view,NemoFile * file,gboolean horizontal)804 nemo_icon_view_set_directory_horizontal_layout (NemoIconView *icon_view,
805                                                 NemoFile     *file,
806                                                 gboolean      horizontal)
807 {
808     sync_directory_monitor_number (icon_view, file);
809 
810     nemo_file_set_boolean_metadata (file,
811                                     NEMO_METADATA_KEY_DESKTOP_GRID_HORIZONTAL,
812                                     FALSE,
813                                     horizontal);
814 }
815 
816 gboolean
nemo_icon_view_get_directory_horizontal_layout(NemoIconView * icon_view,NemoFile * file)817 nemo_icon_view_get_directory_horizontal_layout (NemoIconView *icon_view,
818                                                 NemoFile     *file)
819 {
820     sync_directory_monitor_number (icon_view, file);
821 
822     return nemo_file_get_boolean_metadata (file,
823                                            NEMO_METADATA_KEY_DESKTOP_GRID_HORIZONTAL,
824                                            FALSE);
825 }
826 
827 void
nemo_icon_view_set_directory_grid_adjusts(NemoIconView * icon_view,NemoFile * file,gint horizontal,gint vertical)828 nemo_icon_view_set_directory_grid_adjusts (NemoIconView *icon_view,
829                                            NemoFile     *file,
830                                            gint          horizontal,
831                                            gint          vertical)
832 {
833     sync_directory_monitor_number (icon_view, file);
834 
835     nemo_file_set_desktop_grid_adjusts (file,
836                                         NEMO_METADATA_KEY_DESKTOP_GRID_ADJUST,
837                                         horizontal, vertical);
838 }
839 
840 void
nemo_icon_view_get_directory_grid_adjusts(NemoIconView * icon_view,NemoFile * file,gint * horizontal,gint * vertical)841 nemo_icon_view_get_directory_grid_adjusts (NemoIconView *icon_view,
842                                            NemoFile     *file,
843                                            gint         *horizontal,
844                                            gint         *vertical)
845 {
846     gint h, v;
847 
848     sync_directory_monitor_number (icon_view, file);
849 
850     nemo_file_get_desktop_grid_adjusts (file,
851                                         NEMO_METADATA_KEY_DESKTOP_GRID_ADJUST,
852                                         &h, &v);
853 
854     if (horizontal)
855         *horizontal = h;
856 
857     if (vertical)
858         *vertical = v;
859 }
860 
861 gboolean
nemo_icon_view_set_sort_reversed(NemoIconView * icon_view,gboolean new_value,gboolean set_metadata)862 nemo_icon_view_set_sort_reversed (NemoIconView *icon_view,
863                                   gboolean      new_value,
864                                   gboolean      set_metadata)
865 {
866     if (icon_view->details->sort_reversed == new_value) {
867         return FALSE;
868     }
869 
870     icon_view->details->sort_reversed = new_value;
871 
872     if (set_metadata) {
873         /* Store the new sort setting. */
874         nemo_icon_view_set_directory_sort_reversed (icon_view, nemo_view_get_directory_as_file (NEMO_VIEW (icon_view)), new_value);
875     }
876 
877     /* Update the layout menus to match the new sort-order setting. */
878     update_layout_menus (icon_view);
879 
880     return TRUE;
881 }
882 
883 void
nemo_icon_view_flip_sort_reversed(NemoIconView * icon_view)884 nemo_icon_view_flip_sort_reversed (NemoIconView *icon_view)
885 {
886     nemo_icon_view_set_sort_reversed (icon_view, !icon_view->details->sort_reversed, TRUE);
887 }
888 
889 static const SortCriterion *
get_sort_criterion_by_metadata_text(const char * metadata_text)890 get_sort_criterion_by_metadata_text (const char *metadata_text)
891 {
892 	guint i;
893 
894 	/* Figure out what the new sort setting should be. */
895 	for (i = 0; i < G_N_ELEMENTS (sort_criteria); i++) {
896 		if (g_strcmp0 (sort_criteria[i].metadata_text, metadata_text) == 0) {
897 			return &sort_criteria[i];
898 		}
899 	}
900 	return NULL;
901 }
902 
903 static const SortCriterion *
get_sort_criterion_by_sort_type(NemoFileSortType sort_type)904 get_sort_criterion_by_sort_type (NemoFileSortType sort_type)
905 {
906 	guint i;
907 
908 	/* Figure out what the new sort setting should be. */
909 	for (i = 0; i < G_N_ELEMENTS (sort_criteria); i++) {
910 		if (sort_type == sort_criteria[i].sort_type) {
911 			return &sort_criteria[i];
912 		}
913 	}
914 
915 	return &sort_criteria[0];
916 }
917 
918 #define DEFAULT_ZOOM_LEVEL(icon_view) icon_view->details->compact ? default_compact_zoom_level : default_zoom_level
919 
920 static NemoZoomLevel
get_default_zoom_level(NemoIconView * icon_view)921 get_default_zoom_level (NemoIconView *icon_view)
922 {
923 	NemoZoomLevel default_zoom_level, default_compact_zoom_level;
924 
925 	default_zoom_level = g_settings_get_enum (nemo_icon_view_preferences,
926 						  NEMO_PREFERENCES_ICON_VIEW_DEFAULT_ZOOM_LEVEL);
927 	default_compact_zoom_level = g_settings_get_enum (nemo_compact_view_preferences,
928 							  NEMO_PREFERENCES_COMPACT_VIEW_DEFAULT_ZOOM_LEVEL);
929 
930     if (NEMO_ICON_VIEW_GET_CLASS (icon_view)->use_grid_container) {
931         return NEMO_ZOOM_LEVEL_STANDARD;
932     }
933 
934 	return CLAMP (DEFAULT_ZOOM_LEVEL(icon_view), NEMO_ZOOM_LEVEL_SMALLEST, NEMO_ZOOM_LEVEL_LARGEST);
935 }
936 
937 static void
set_labels_beside_icons(NemoIconView * icon_view)938 set_labels_beside_icons (NemoIconView *icon_view)
939 {
940 	gboolean labels_beside;
941 
942 	if (nemo_icon_view_supports_labels_beside_icons (icon_view)) {
943 		labels_beside = nemo_icon_view_is_compact (icon_view) ||
944 			g_settings_get_boolean (nemo_icon_view_preferences,
945 						NEMO_PREFERENCES_ICON_VIEW_LABELS_BESIDE_ICONS);
946 
947 		if (labels_beside) {
948 			nemo_icon_container_set_label_position
949 				(get_icon_container (icon_view),
950 				 NEMO_ICON_LABEL_POSITION_BESIDE);
951 		} else {
952 			nemo_icon_container_set_label_position
953 				(get_icon_container (icon_view),
954 				 NEMO_ICON_LABEL_POSITION_UNDER);
955 		}
956 	}
957 }
958 
959 static void
set_columns_same_width(NemoIconView * icon_view)960 set_columns_same_width (NemoIconView *icon_view)
961 {
962 	gboolean all_columns_same_width;
963 
964 	if (nemo_icon_view_is_compact (icon_view)) {
965 		all_columns_same_width = g_settings_get_boolean (nemo_compact_view_preferences,
966 								 NEMO_PREFERENCES_COMPACT_VIEW_ALL_COLUMNS_SAME_WIDTH);
967 		nemo_icon_container_set_all_columns_same_width (get_icon_container (icon_view), all_columns_same_width);
968 	}
969 }
970 
971 static void
nemo_icon_view_begin_loading(NemoView * view)972 nemo_icon_view_begin_loading (NemoView *view)
973 {
974 	NemoIconView *icon_view;
975 	GtkWidget *icon_container;
976 	NemoFile *file;
977 	int level;
978     int h_adjust, v_adjust;
979 	char *sort_name, *uri;
980 
981 	g_return_if_fail (NEMO_IS_ICON_VIEW (view));
982 
983 	icon_view = NEMO_ICON_VIEW (view);
984 	file = nemo_view_get_directory_as_file (view);
985 	uri = nemo_file_get_uri (file);
986 	icon_container = GTK_WIDGET (get_icon_container (icon_view));
987 
988     nemo_icon_container_set_ok_to_load_deferred_attrs (NEMO_ICON_CONTAINER (icon_container), FALSE);
989 
990 	nemo_icon_container_begin_loading (NEMO_ICON_CONTAINER (icon_container));
991 
992 	nemo_icon_container_set_allow_moves (NEMO_ICON_CONTAINER (icon_container),
993 						 !eel_uri_is_search (uri));
994 
995 	g_free (uri);
996 
997 	/* Set up the zoom level from the metadata. */
998 	if (nemo_view_supports_zooming (NEMO_VIEW (icon_view))) {
999         if (nemo_global_preferences_get_ignore_view_metadata () && !NEMO_ICON_VIEW_GET_CLASS (view)->use_grid_container) {
1000             if (nemo_window_get_ignore_meta_zoom_level (nemo_view_get_nemo_window (view)) == -1) {
1001                 nemo_window_set_ignore_meta_zoom_level (nemo_view_get_nemo_window (view), get_default_zoom_level (icon_view));
1002             }
1003 
1004             level = nemo_window_get_ignore_meta_zoom_level (nemo_view_get_nemo_window (NEMO_VIEW (icon_view)));
1005         } else {
1006             sync_directory_monitor_number (icon_view, file);
1007 
1008             if (icon_view->details->compact) {
1009                 level = nemo_file_get_integer_metadata (file,
1010                                                         NEMO_METADATA_KEY_COMPACT_VIEW_ZOOM_LEVEL,
1011                                                         get_default_zoom_level (icon_view));
1012             } else {
1013                 level = nemo_file_get_integer_metadata (file,
1014                                                         NEMO_METADATA_KEY_ICON_VIEW_ZOOM_LEVEL,
1015                                                         get_default_zoom_level (icon_view));
1016     		}
1017         }
1018 
1019 		nemo_icon_view_set_zoom_level (icon_view, level, TRUE);
1020 	}
1021 
1022 	/* Set the sort mode.
1023 	 * It's OK not to resort the icons because the
1024 	 * container doesn't have any icons at this point.
1025 	 */
1026 	sort_name = nemo_icon_view_get_directory_sort_by (icon_view, file);
1027 	set_sort_criterion (icon_view, get_sort_criterion_by_metadata_text (sort_name), FALSE);
1028 	g_free (sort_name);
1029 
1030 	/* Set the sort direction from the metadata. */
1031 	nemo_icon_view_set_sort_reversed (icon_view, nemo_icon_view_get_directory_sort_reversed (icon_view, file), FALSE);
1032 
1033     nemo_icon_container_set_horizontal_layout (get_icon_container (icon_view),
1034                                                nemo_icon_view_get_directory_horizontal_layout (icon_view, file));
1035 
1036 	nemo_icon_container_set_keep_aligned (get_icon_container (icon_view),
1037                     nemo_icon_view_get_directory_keep_aligned (icon_view, file));
1038 
1039     nemo_icon_view_get_directory_grid_adjusts (NEMO_ICON_VIEW (view),
1040                                                file,
1041                                                &h_adjust,
1042                                                &v_adjust);
1043 
1044     nemo_icon_container_set_grid_adjusts (get_icon_container (icon_view), h_adjust, v_adjust);
1045 
1046 	set_labels_beside_icons (icon_view);
1047 	set_columns_same_width (icon_view);
1048 
1049 	/* We must set auto-layout last, because it invokes the layout_changed
1050 	 * callback, which works incorrectly if the other layout criteria are
1051 	 * not already set up properly (see bug 6500, e.g.)
1052 	 */
1053 	nemo_icon_container_set_auto_layout
1054 		(get_icon_container (icon_view),
1055 		 nemo_icon_view_get_directory_auto_layout (icon_view, file));
1056 
1057 	/* e.g. keep aligned may have changed */
1058 	update_layout_menus (icon_view);
1059 }
1060 
1061 static void
icon_view_notify_clipboard_info(NemoClipboardMonitor * monitor,NemoClipboardInfo * info,NemoIconView * icon_view)1062 icon_view_notify_clipboard_info (NemoClipboardMonitor *monitor,
1063                                  NemoClipboardInfo *info,
1064                                  NemoIconView *icon_view)
1065 {
1066 	GList *icon_data;
1067 
1068 	icon_data = NULL;
1069 	if (info && info->cut) {
1070 		icon_data = info->files;
1071 	}
1072 
1073 	nemo_icon_container_set_highlighted_for_clipboard (
1074 							       get_icon_container (icon_view), icon_data);
1075 }
1076 
1077 static void
nemo_icon_view_end_loading(NemoView * view,gboolean all_files_seen)1078 nemo_icon_view_end_loading (NemoView *view,
1079 			  gboolean all_files_seen)
1080 {
1081 	NemoIconView *icon_view;
1082 	GtkWidget *icon_container;
1083 	NemoClipboardMonitor *monitor;
1084 	NemoClipboardInfo *info;
1085 
1086 	icon_view = NEMO_ICON_VIEW (view);
1087 
1088 	icon_container = GTK_WIDGET (get_icon_container (icon_view));
1089 	nemo_icon_container_end_loading (NEMO_ICON_CONTAINER (icon_container), all_files_seen);
1090 
1091 	monitor = nemo_clipboard_monitor_get ();
1092 	info = nemo_clipboard_monitor_get_clipboard_info (monitor);
1093     nemo_icon_container_set_ok_to_load_deferred_attrs (NEMO_ICON_CONTAINER (icon_container), TRUE);
1094 	icon_view_notify_clipboard_info (monitor, info, icon_view);
1095 }
1096 
1097 static NemoZoomLevel
nemo_icon_view_get_zoom_level(NemoView * view)1098 nemo_icon_view_get_zoom_level (NemoView *view)
1099 {
1100 	g_return_val_if_fail (NEMO_IS_ICON_VIEW (view), NEMO_ZOOM_LEVEL_STANDARD);
1101 
1102 	return nemo_icon_container_get_zoom_level (get_icon_container (NEMO_ICON_VIEW (view)));
1103 }
1104 
1105 static void
nemo_icon_view_set_zoom_level(NemoIconView * view,NemoZoomLevel new_level,gboolean always_emit)1106 nemo_icon_view_set_zoom_level (NemoIconView *view,
1107 				   NemoZoomLevel new_level,
1108 				   gboolean always_emit)
1109 {
1110 	NemoIconContainer *icon_container;
1111 
1112 	g_return_if_fail (NEMO_IS_ICON_VIEW (view));
1113 	g_return_if_fail (new_level >= NEMO_ZOOM_LEVEL_SMALLEST &&
1114 			  new_level <= NEMO_ZOOM_LEVEL_LARGEST);
1115 
1116 	icon_container = get_icon_container (view);
1117 	if (nemo_icon_container_get_zoom_level (icon_container) == new_level) {
1118 		if (always_emit) {
1119 			g_signal_emit_by_name (view, "zoom_level_changed");
1120 		}
1121 		return;
1122 	}
1123 
1124     if (nemo_global_preferences_get_ignore_view_metadata () && !NEMO_ICON_VIEW_GET_CLASS (view)->use_grid_container) {
1125         nemo_window_set_ignore_meta_zoom_level (nemo_view_get_nemo_window (NEMO_VIEW (view)), new_level);
1126     } else {
1127         sync_directory_monitor_number (view, nemo_view_get_directory_as_file (NEMO_VIEW (view)));
1128 
1129         if (view->details->compact) {
1130             nemo_file_set_integer_metadata (nemo_view_get_directory_as_file (NEMO_VIEW (view)),
1131                                             NEMO_METADATA_KEY_COMPACT_VIEW_ZOOM_LEVEL,
1132                                             get_default_zoom_level (view),
1133                                             new_level);
1134         } else {
1135             nemo_file_set_integer_metadata (nemo_view_get_directory_as_file (NEMO_VIEW (view)),
1136                                             NEMO_METADATA_KEY_ICON_VIEW_ZOOM_LEVEL,
1137                                             get_default_zoom_level (view),
1138                                             new_level);
1139         }
1140     }
1141 
1142 	nemo_icon_container_set_zoom_level (icon_container, new_level);
1143 
1144 	g_signal_emit_by_name (view, "zoom_level_changed");
1145 
1146 	if (nemo_view_get_active (NEMO_VIEW (view))) {
1147 		nemo_view_update_menus (NEMO_VIEW (view));
1148 	}
1149 }
1150 
1151 static void
nemo_icon_view_bump_zoom_level(NemoView * view,int zoom_increment)1152 nemo_icon_view_bump_zoom_level (NemoView *view, int zoom_increment)
1153 {
1154 	NemoZoomLevel new_level;
1155 
1156 	g_return_if_fail (NEMO_IS_ICON_VIEW (view));
1157 
1158 	new_level = nemo_icon_view_get_zoom_level (view) + zoom_increment;
1159 
1160 	if (new_level >= NEMO_ZOOM_LEVEL_SMALLEST &&
1161 	    new_level <= NEMO_ZOOM_LEVEL_LARGEST) {
1162 		nemo_view_zoom_to_level (view, new_level);
1163 	}
1164 }
1165 
1166 static void
nemo_icon_view_zoom_to_level(NemoView * view,NemoZoomLevel zoom_level)1167 nemo_icon_view_zoom_to_level (NemoView *view,
1168 			    NemoZoomLevel zoom_level)
1169 {
1170 	NemoIconView *icon_view;
1171 
1172 	g_assert (NEMO_IS_ICON_VIEW (view));
1173 
1174 	icon_view = NEMO_ICON_VIEW (view);
1175 	nemo_icon_view_set_zoom_level (icon_view, zoom_level, FALSE);
1176 }
1177 
1178 static void
nemo_icon_view_restore_default_zoom_level(NemoView * view)1179 nemo_icon_view_restore_default_zoom_level (NemoView *view)
1180 {
1181 	NemoIconView *icon_view;
1182 
1183 	g_return_if_fail (NEMO_IS_ICON_VIEW (view));
1184 
1185 	icon_view = NEMO_ICON_VIEW (view);
1186 	nemo_view_zoom_to_level
1187 		(view, get_default_zoom_level (icon_view));
1188 }
1189 
1190 static NemoZoomLevel
nemo_icon_view_get_default_zoom_level(NemoView * view)1191 nemo_icon_view_get_default_zoom_level (NemoView *view)
1192 {
1193     g_return_val_if_fail (NEMO_IS_ICON_VIEW (view), NEMO_ZOOM_LEVEL_NULL);
1194 
1195     return get_default_zoom_level(NEMO_ICON_VIEW (view));
1196 }
1197 
1198 static gboolean
nemo_icon_view_can_zoom_in(NemoView * view)1199 nemo_icon_view_can_zoom_in (NemoView *view)
1200 {
1201 	g_return_val_if_fail (NEMO_IS_ICON_VIEW (view), FALSE);
1202 
1203 	return nemo_icon_view_get_zoom_level (view)
1204 		< NEMO_ZOOM_LEVEL_LARGEST;
1205 }
1206 
1207 static gboolean
nemo_icon_view_can_zoom_out(NemoView * view)1208 nemo_icon_view_can_zoom_out (NemoView *view)
1209 {
1210 	g_return_val_if_fail (NEMO_IS_ICON_VIEW (view), FALSE);
1211 
1212 	return nemo_icon_view_get_zoom_level (view)
1213 		> NEMO_ZOOM_LEVEL_SMALLEST;
1214 }
1215 
1216 static gboolean
nemo_icon_view_is_empty(NemoView * view)1217 nemo_icon_view_is_empty (NemoView *view)
1218 {
1219 	g_assert (NEMO_IS_ICON_VIEW (view));
1220 
1221 	return nemo_icon_container_is_empty
1222 		(get_icon_container (NEMO_ICON_VIEW (view)));
1223 }
1224 
1225 static GList *
nemo_icon_view_get_selection(NemoView * view)1226 nemo_icon_view_get_selection (NemoView *view)
1227 {
1228 	GList *list;
1229 
1230 	g_return_val_if_fail (NEMO_IS_ICON_VIEW (view), NULL);
1231 
1232 	list = nemo_icon_container_get_selection
1233 		(get_icon_container (NEMO_ICON_VIEW (view)));
1234 	nemo_file_list_ref (list);
1235 	return list;
1236 }
1237 
1238 static GList *
nemo_icon_view_peek_selection(NemoView * view)1239 nemo_icon_view_peek_selection (NemoView *view)
1240 {
1241     GList *list;
1242 
1243     g_return_val_if_fail (NEMO_IS_ICON_VIEW (view), NULL);
1244 
1245     list = nemo_icon_container_peek_selection (get_icon_container (NEMO_ICON_VIEW (view)));
1246     nemo_file_list_ref (list);
1247     return list;
1248 }
1249 
1250 static gint
nemo_icon_view_get_selection_count(NemoView * view)1251 nemo_icon_view_get_selection_count (NemoView *view)
1252 {
1253     g_return_val_if_fail (NEMO_IS_ICON_VIEW (view), 0);
1254 
1255     return nemo_icon_container_get_selection_count (get_icon_container (NEMO_ICON_VIEW (view)));
1256 }
1257 
1258 static void
count_item(NemoIconData * icon_data,gpointer callback_data)1259 count_item (NemoIconData *icon_data,
1260 	    gpointer callback_data)
1261 {
1262 	guint *count;
1263 
1264 	count = callback_data;
1265 	(*count)++;
1266 }
1267 
1268 static guint
nemo_icon_view_get_item_count(NemoView * view)1269 nemo_icon_view_get_item_count (NemoView *view)
1270 {
1271 	guint count;
1272 
1273 	g_return_val_if_fail (NEMO_IS_ICON_VIEW (view), 0);
1274 
1275 	count = 0;
1276 
1277 	nemo_icon_container_for_each
1278 		(get_icon_container (NEMO_ICON_VIEW (view)),
1279 		 count_item, &count);
1280 
1281 	return count;
1282 }
1283 
1284 void
nemo_icon_view_set_sort_criterion_by_sort_type(NemoIconView * icon_view,NemoFileSortType sort_type)1285 nemo_icon_view_set_sort_criterion_by_sort_type (NemoIconView     *icon_view,
1286                                                 NemoFileSortType  sort_type)
1287 {
1288 	const SortCriterion *sort;
1289 
1290 	g_assert (NEMO_IS_ICON_VIEW (icon_view));
1291 
1292 	sort = get_sort_criterion_by_sort_type (sort_type);
1293 	g_return_if_fail (sort != NULL);
1294 
1295 	if (sort == icon_view->details->sort
1296 	    && nemo_icon_view_using_auto_layout (icon_view)) {
1297 		return;
1298 	}
1299 
1300 	set_sort_criterion (icon_view, sort, TRUE);
1301 	nemo_icon_container_sort (get_icon_container (icon_view));
1302 	nemo_icon_view_reveal_selection (NEMO_VIEW (icon_view));
1303 }
1304 
1305 
1306 static void
action_reversed_order_callback(GtkAction * action,gpointer user_data)1307 action_reversed_order_callback (GtkAction *action,
1308 				gpointer user_data)
1309 {
1310 	NemoIconView *icon_view;
1311 
1312 	icon_view = NEMO_ICON_VIEW (user_data);
1313 
1314 	if (nemo_icon_view_set_sort_reversed (icon_view,
1315 			       gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)),
1316 			       TRUE)) {
1317 		nemo_icon_container_sort (get_icon_container (icon_view));
1318 		nemo_icon_view_reveal_selection (NEMO_VIEW (icon_view));
1319 	}
1320 }
1321 
1322 static void
action_keep_aligned_callback(GtkAction * action,gpointer user_data)1323 action_keep_aligned_callback (GtkAction *action,
1324 			      gpointer user_data)
1325 {
1326 	NemoIconView *icon_view;
1327 	NemoFile *file;
1328 	gboolean keep_aligned;
1329 
1330 	icon_view = NEMO_ICON_VIEW (user_data);
1331 
1332 	keep_aligned = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1333 
1334 	file = nemo_view_get_directory_as_file (NEMO_VIEW (icon_view));
1335 	nemo_icon_view_set_directory_keep_aligned (icon_view,
1336 						 file,
1337 						 keep_aligned);
1338 
1339 	nemo_icon_container_set_keep_aligned (get_icon_container (icon_view),
1340 						  keep_aligned);
1341 }
1342 
1343 static void
switch_to_manual_layout(NemoIconView * icon_view)1344 switch_to_manual_layout (NemoIconView *icon_view)
1345 {
1346 	if (!nemo_icon_view_using_auto_layout (icon_view)) {
1347 		return;
1348 	}
1349 
1350 	icon_view->details->sort = &sort_criteria[0];
1351 
1352 	nemo_icon_container_set_auto_layout
1353 		(get_icon_container (icon_view), FALSE);
1354 }
1355 
1356 static void
layout_changed_callback(NemoIconContainer * container,NemoIconView * icon_view)1357 layout_changed_callback (NemoIconContainer *container,
1358 			 NemoIconView *icon_view)
1359 {
1360 	NemoFile *file;
1361 
1362 	g_assert (NEMO_IS_ICON_VIEW (icon_view));
1363 	g_assert (container == get_icon_container (icon_view));
1364 
1365 	file = nemo_view_get_directory_as_file (NEMO_VIEW (icon_view));
1366 
1367 	if (file != NULL) {
1368 		nemo_icon_view_set_directory_auto_layout
1369 			(icon_view,
1370 			 file,
1371 			 nemo_icon_view_using_auto_layout (icon_view));
1372 	}
1373 
1374 	update_layout_menus (icon_view);
1375 }
1376 
1377 static gboolean
nemo_icon_view_can_rename_file(NemoView * view,NemoFile * file)1378 nemo_icon_view_can_rename_file (NemoView *view, NemoFile *file)
1379 {
1380 	if (!(nemo_icon_view_get_zoom_level (view) > NEMO_ZOOM_LEVEL_SMALLEST)) {
1381 		return FALSE;
1382 	}
1383 
1384 	return NEMO_VIEW_CLASS(nemo_icon_view_parent_class)->can_rename_file (view, file);
1385 }
1386 
1387 static void
nemo_icon_view_start_renaming_file(NemoView * view,NemoFile * file,gboolean select_all)1388 nemo_icon_view_start_renaming_file (NemoView *view,
1389 				  NemoFile *file,
1390 				  gboolean select_all)
1391 {
1392 	/* call parent class to make sure the right icon is selected */
1393 	NEMO_VIEW_CLASS(nemo_icon_view_parent_class)->start_renaming_file (view, file, select_all);
1394 
1395 	/* start renaming */
1396 	nemo_icon_container_start_renaming_selected_item
1397 		(get_icon_container (NEMO_ICON_VIEW (view)), select_all);
1398 }
1399 
1400 static const GtkActionEntry icon_view_entries[] = {
1401   /* name, stock id, label */  { "Arrange Items", NULL, N_("Arran_ge Items") },
1402   /* name, stock id */         { "Clean Up", NULL,
1403   /* label, accelerator */       N_("_Organize by Name"), NULL,
1404   /* tooltip */                  N_("Reposition icons to better fit in the window and avoid overlapping"),
1405                                  G_CALLBACK (action_clean_up_callback) },
1406 };
1407 
1408 static const GtkToggleActionEntry icon_view_toggle_entries[] = {
1409 
1410   /* name, stock id */      { "Reversed Order", NULL,
1411   /* label, accelerator */    N_("Re_versed Order"), NULL,
1412   /* tooltip */               N_("Display icons in the opposite order"),
1413                               G_CALLBACK (action_reversed_order_callback),
1414                               0 },
1415   /* name, stock id */      { "Keep Aligned", NULL,
1416   /* label, accelerator */    N_("_Keep Aligned"), NULL,
1417   /* tooltip */               N_("Keep icons lined up on a grid"),
1418                               G_CALLBACK (action_keep_aligned_callback),
1419                               0 },
1420 };
1421 
1422 static const GtkRadioActionEntry arrange_radio_entries[] = {
1423   { "Manual Layout", NULL,
1424     N_("_Manually"), NULL,
1425     N_("Leave icons wherever they are dropped"),
1426     NEMO_FILE_SORT_NONE },
1427   { "Sort by Name", NULL,
1428     N_("By _Name"), NULL,
1429     N_("Keep icons sorted by name in rows"),
1430     NEMO_FILE_SORT_BY_DISPLAY_NAME },
1431   { "Sort by Size", NULL,
1432     N_("By _Size"), NULL,
1433     N_("Keep icons sorted by size in rows"),
1434     NEMO_FILE_SORT_BY_SIZE },
1435   { "Sort by Type", NULL,
1436     N_("By _Type"), NULL,
1437     N_("Keep icons sorted by type in rows"),
1438     NEMO_FILE_SORT_BY_TYPE },
1439   { "Sort by Detailed Type", NULL,
1440     N_("By _Detailed Type"), NULL,
1441     N_("Keep icons sorted by detailed type in rows"),
1442     NEMO_FILE_SORT_BY_DETAILED_TYPE },
1443   { "Sort by Modification Date", NULL,
1444     N_("By Modification _Date"), NULL,
1445     N_("Keep icons sorted by modification date in rows"),
1446     NEMO_FILE_SORT_BY_MTIME },
1447   { "Sort by Trash Time", NULL,
1448     N_("By T_rash Time"), NULL,
1449     N_("Keep icons sorted by trash time in rows"),
1450     NEMO_FILE_SORT_BY_TRASHED_TIME },
1451 };
1452 
1453 static void
nemo_icon_view_merge_menus(NemoView * view)1454 nemo_icon_view_merge_menus (NemoView *view)
1455 {
1456 	NemoIconView *icon_view;
1457 	GtkUIManager *ui_manager;
1458 	GtkActionGroup *action_group;
1459 	GtkAction *action;
1460 
1461         g_assert (NEMO_IS_ICON_VIEW (view));
1462 
1463 	NEMO_VIEW_CLASS (nemo_icon_view_parent_class)->merge_menus (view);
1464 
1465 	icon_view = NEMO_ICON_VIEW (view);
1466 
1467 	ui_manager = nemo_view_get_ui_manager (NEMO_VIEW (icon_view));
1468 
1469 	action_group = gtk_action_group_new ("IconViewActions");
1470 	gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1471 	icon_view->details->icon_action_group = action_group;
1472 	gtk_action_group_add_actions (action_group,
1473 				      icon_view_entries, G_N_ELEMENTS (icon_view_entries),
1474 				      icon_view);
1475 	gtk_action_group_add_toggle_actions (action_group,
1476 					     icon_view_toggle_entries, G_N_ELEMENTS (icon_view_toggle_entries),
1477 					     icon_view);
1478 	gtk_action_group_add_radio_actions (action_group,
1479 					    arrange_radio_entries,
1480 					    G_N_ELEMENTS (arrange_radio_entries),
1481 					    -1,
1482 					    G_CALLBACK (action_sort_radio_callback),
1483 					    icon_view);
1484 
1485 	gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
1486 	g_object_unref (action_group); /* owned by ui manager */
1487 
1488 	icon_view->details->icon_merge_id =
1489 		gtk_ui_manager_add_ui_from_resource (ui_manager, "/org/nemo/nemo-icon-view-ui.xml", NULL);
1490 
1491 	/* Do one-time state-setting here; context-dependent state-setting
1492 	 * is done in update_menus.
1493 	 */
1494 	if (!nemo_icon_view_supports_auto_layout (icon_view)) {
1495 		action = gtk_action_group_get_action (action_group,
1496 						      NEMO_ACTION_ARRANGE_ITEMS);
1497 		gtk_action_set_visible (action, FALSE);
1498 	}
1499 
1500 	update_layout_menus (icon_view);
1501 }
1502 
1503 static void
nemo_icon_view_unmerge_menus(NemoView * view)1504 nemo_icon_view_unmerge_menus (NemoView *view)
1505 {
1506 	NemoIconView *icon_view;
1507 	GtkUIManager *ui_manager;
1508 
1509 	icon_view = NEMO_ICON_VIEW (view);
1510 
1511 	NEMO_VIEW_CLASS (nemo_icon_view_parent_class)->unmerge_menus (view);
1512 
1513 	ui_manager = nemo_view_get_ui_manager (view);
1514 	if (ui_manager != NULL) {
1515 		nemo_ui_unmerge_ui (ui_manager,
1516 					&icon_view->details->icon_merge_id,
1517 					&icon_view->details->icon_action_group);
1518 	}
1519 }
1520 
1521 static void
nemo_icon_view_update_menus(NemoView * view)1522 nemo_icon_view_update_menus (NemoView *view)
1523 {
1524     NemoIconView *icon_view;
1525     GtkAction *action;
1526     gboolean editable;
1527 
1528     icon_view = NEMO_ICON_VIEW (view);
1529 
1530 	NEMO_VIEW_CLASS (nemo_icon_view_parent_class)->update_menus(view);
1531 
1532 	editable = nemo_view_is_editable (view);
1533 	action = gtk_action_group_get_action (icon_view->details->icon_action_group,
1534 					      NEMO_ACTION_MANUAL_LAYOUT);
1535 	gtk_action_set_sensitive (action, editable);
1536 }
1537 
1538 static void
nemo_icon_view_reset_to_defaults(NemoView * view)1539 nemo_icon_view_reset_to_defaults (NemoView *view)
1540 {
1541 	NemoIconContainer *icon_container;
1542 	NemoIconView *icon_view;
1543 
1544 	icon_view = NEMO_ICON_VIEW (view);
1545 	icon_container = get_icon_container (icon_view);
1546 
1547 	clear_sort_criterion (icon_view);
1548 	nemo_icon_container_set_keep_aligned
1549 		(icon_container, get_default_directory_keep_aligned ());
1550 
1551 	nemo_icon_container_sort (icon_container);
1552 
1553 	update_layout_menus (icon_view);
1554 
1555 	nemo_icon_view_restore_default_zoom_level (view);
1556 
1557     if (nemo_global_preferences_get_ignore_view_metadata ()) {
1558         NemoWindow *window = nemo_view_get_nemo_window (view);
1559         nemo_window_set_ignore_meta_zoom_level (window, NEMO_ZOOM_LEVEL_NULL);
1560     }
1561 }
1562 
1563 static void
nemo_icon_view_select_all(NemoView * view)1564 nemo_icon_view_select_all (NemoView *view)
1565 {
1566 	NemoIconContainer *icon_container;
1567 
1568 	g_return_if_fail (NEMO_IS_ICON_VIEW (view));
1569 
1570 	icon_container = get_icon_container (NEMO_ICON_VIEW (view));
1571         nemo_icon_container_select_all (icon_container);
1572 }
1573 
1574 static void
nemo_icon_view_reveal_selection(NemoView * view)1575 nemo_icon_view_reveal_selection (NemoView *view)
1576 {
1577 	GList *selection;
1578 
1579 	g_return_if_fail (NEMO_IS_ICON_VIEW (view));
1580 
1581         selection = nemo_view_get_selection (view);
1582 
1583 	/* Make sure at least one of the selected items is scrolled into view */
1584 	if (selection != NULL) {
1585 		nemo_icon_container_reveal
1586 			(get_icon_container (NEMO_ICON_VIEW (view)),
1587 			 selection->data);
1588 	}
1589 
1590         nemo_file_list_free (selection);
1591 }
1592 
1593 static GArray *
nemo_icon_view_get_selected_icon_locations(NemoView * view)1594 nemo_icon_view_get_selected_icon_locations (NemoView *view)
1595 {
1596 	g_return_val_if_fail (NEMO_IS_ICON_VIEW (view), NULL);
1597 
1598 	return nemo_icon_container_get_selected_icon_locations
1599 		(get_icon_container (NEMO_ICON_VIEW (view)));
1600 }
1601 
1602 
1603 static void
nemo_icon_view_set_selection(NemoView * view,GList * selection)1604 nemo_icon_view_set_selection (NemoView *view, GList *selection)
1605 {
1606 	g_return_if_fail (NEMO_IS_ICON_VIEW (view));
1607 
1608 	nemo_icon_container_set_selection
1609 		(get_icon_container (NEMO_ICON_VIEW (view)), selection);
1610 }
1611 
1612 static void
nemo_icon_view_invert_selection(NemoView * view)1613 nemo_icon_view_invert_selection (NemoView *view)
1614 {
1615 	g_return_if_fail (NEMO_IS_ICON_VIEW (view));
1616 
1617 	nemo_icon_container_invert_selection
1618 		(get_icon_container (NEMO_ICON_VIEW (view)));
1619 }
1620 
1621 static gboolean
nemo_icon_view_using_manual_layout(NemoView * view)1622 nemo_icon_view_using_manual_layout (NemoView *view)
1623 {
1624 	g_return_val_if_fail (NEMO_IS_ICON_VIEW (view), FALSE);
1625 
1626 	return !nemo_icon_view_using_auto_layout (NEMO_ICON_VIEW (view));
1627 }
1628 
1629 static void
nemo_icon_view_widget_to_file_operation_position(NemoView * view,GdkPoint * position)1630 nemo_icon_view_widget_to_file_operation_position (NemoView *view,
1631 						GdkPoint *position)
1632 {
1633 	g_assert (NEMO_IS_ICON_VIEW (view));
1634 
1635 	nemo_icon_container_widget_to_file_operation_position
1636 		(get_icon_container (NEMO_ICON_VIEW (view)), position);
1637 }
1638 
1639 static void
icon_container_activate_callback(NemoIconContainer * container,GList * file_list,NemoIconView * icon_view)1640 icon_container_activate_callback (NemoIconContainer *container,
1641 				  GList *file_list,
1642 				  NemoIconView *icon_view)
1643 {
1644 	g_assert (NEMO_IS_ICON_VIEW (icon_view));
1645 	g_assert (container == get_icon_container (icon_view));
1646 
1647 	nemo_view_activate_files (NEMO_VIEW (icon_view),
1648 				      file_list,
1649 				      0, TRUE);
1650 }
1651 
1652 static void
icon_container_activate_previewer_callback(NemoIconContainer * container,GList * file_list,GArray * locations,NemoIconView * icon_view)1653 icon_container_activate_previewer_callback (NemoIconContainer *container,
1654 					    GList *file_list,
1655 					    GArray *locations,
1656 					    NemoIconView *icon_view)
1657 {
1658 	g_assert (NEMO_IS_ICON_VIEW (icon_view));
1659 	g_assert (container == get_icon_container (icon_view));
1660 
1661 	nemo_view_preview_files (NEMO_VIEW (icon_view),
1662 				     file_list, locations);
1663 }
1664 
1665 /* this is called in one of these cases:
1666  * - we activate with enter holding shift
1667  * - we activate with space holding shift
1668  * - we double click an icon holding shift
1669  * - we middle click an icon
1670  *
1671  * If we don't open in new windows by default, the behavior should be
1672  * - middle click, shift + activate -> open in new tab
1673  * - shift + double click -> open in new window
1674  *
1675  * If we open in new windows by default, the behaviour should be
1676  * - middle click, or shift + activate, or shift + double-click -> close parent
1677  */
1678 static void
icon_container_activate_alternate_callback(NemoIconContainer * container,GList * file_list,NemoIconView * icon_view)1679 icon_container_activate_alternate_callback (NemoIconContainer *container,
1680 					    GList *file_list,
1681 					    NemoIconView *icon_view)
1682 {
1683 	GdkEvent *event;
1684 	GdkEventButton *button_event;
1685 	GdkEventKey *key_event;
1686 	gboolean open_in_tab, open_in_window, close_behind;
1687 	NemoWindowOpenFlags flags;
1688 
1689 	g_assert (NEMO_IS_ICON_VIEW (icon_view));
1690 	g_assert (container == get_icon_container (icon_view));
1691 
1692 	flags = 0;
1693 	event = gtk_get_current_event ();
1694 	open_in_tab = FALSE;
1695 	open_in_window = FALSE;
1696 	close_behind = FALSE;
1697 
1698 	if (g_settings_get_boolean (nemo_preferences,
1699 				    NEMO_PREFERENCES_ALWAYS_USE_BROWSER)) {
1700 		if (event->type == GDK_BUTTON_PRESS ||
1701 		    event->type == GDK_BUTTON_RELEASE ||
1702 		    event->type == GDK_2BUTTON_PRESS ||
1703 		    event->type == GDK_3BUTTON_PRESS) {
1704 			button_event = (GdkEventButton *) event;
1705 			open_in_window = ((button_event->state & GDK_SHIFT_MASK) != 0);
1706 			open_in_tab = !open_in_window;
1707 		} else if (event->type == GDK_KEY_PRESS ||
1708 			   event->type == GDK_KEY_RELEASE) {
1709 			key_event = (GdkEventKey *) event;
1710 			open_in_tab = ((key_event->state & GDK_SHIFT_MASK) != 0);
1711 		}
1712 	} else {
1713 		close_behind = TRUE;
1714 	}
1715 
1716 	if (open_in_tab) {
1717 		flags |= NEMO_WINDOW_OPEN_FLAG_NEW_TAB;
1718 	}
1719 
1720 	if (open_in_window) {
1721 		flags |= NEMO_WINDOW_OPEN_FLAG_NEW_WINDOW;
1722 	}
1723 
1724 	if (close_behind) {
1725 		flags |= NEMO_WINDOW_OPEN_FLAG_CLOSE_BEHIND;
1726 	}
1727 
1728 	DEBUG ("Activate alternate, open in tab %d, close behind %d, new window %d\n",
1729 	       open_in_tab, close_behind, open_in_window);
1730 
1731 	nemo_view_activate_files (NEMO_VIEW (icon_view),
1732 				      file_list,
1733 				      flags,
1734 				      TRUE);
1735 }
1736 
1737 static void
band_select_started_callback(NemoIconContainer * container,NemoIconView * icon_view)1738 band_select_started_callback (NemoIconContainer *container,
1739 			      NemoIconView *icon_view)
1740 {
1741 	g_assert (NEMO_IS_ICON_VIEW (icon_view));
1742 	g_assert (container == get_icon_container (icon_view));
1743 
1744 	nemo_view_start_batching_selection_changes (NEMO_VIEW (icon_view));
1745 }
1746 
1747 static void
band_select_ended_callback(NemoIconContainer * container,NemoIconView * icon_view)1748 band_select_ended_callback (NemoIconContainer *container,
1749 			    NemoIconView *icon_view)
1750 {
1751 	g_assert (NEMO_IS_ICON_VIEW (icon_view));
1752 	g_assert (container == get_icon_container (icon_view));
1753 
1754 	nemo_view_stop_batching_selection_changes (NEMO_VIEW (icon_view));
1755 }
1756 
1757 int
nemo_icon_view_compare_files(NemoIconView * icon_view,NemoFile * a,NemoFile * b)1758 nemo_icon_view_compare_files (NemoIconView   *icon_view,
1759 				  NemoFile *a,
1760 				  NemoFile *b)
1761 {
1762 	return nemo_file_compare_for_sort
1763 		(a, b, icon_view->details->sort->sort_type,
1764 		 /* Use type-unsafe cast for performance */
1765 		 nemo_view_should_sort_directories_first ((NemoView *)icon_view),
1766 		 icon_view->details->sort_reversed);
1767 }
1768 
1769 static int
compare_files(NemoView * icon_view,NemoFile * a,NemoFile * b)1770 compare_files (NemoView   *icon_view,
1771 	       NemoFile *a,
1772 	       NemoFile *b)
1773 {
1774 	return nemo_icon_view_compare_files ((NemoIconView *)icon_view, a, b);
1775 }
1776 
1777 static void
nemo_icon_view_screen_changed(GtkWidget * widget,GdkScreen * previous_screen)1778 nemo_icon_view_screen_changed (GtkWidget *widget,
1779 				   GdkScreen *previous_screen)
1780 {
1781 	NemoView *view;
1782 	GList *files, *l;
1783 	NemoFile *file;
1784 	NemoDirectory *directory;
1785 	NemoIconContainer *icon_container;
1786 
1787 	if (GTK_WIDGET_CLASS (nemo_icon_view_parent_class)->screen_changed) {
1788 		GTK_WIDGET_CLASS (nemo_icon_view_parent_class)->screen_changed (widget, previous_screen);
1789 	}
1790 
1791 	view = NEMO_VIEW (widget);
1792 	if (NEMO_ICON_VIEW (view)->details->is_desktop) {
1793 		icon_container = get_icon_container (NEMO_ICON_VIEW (view));
1794 
1795 		directory = nemo_view_get_model (view);
1796 		files = nemo_directory_get_file_list (directory);
1797 
1798 		for (l = files; l != NULL; l = l->next) {
1799 			file = l->data;
1800 
1801 			if (!should_show_file_on_screen (view, file)) {
1802 				nemo_icon_view_remove_file (view, file, directory);
1803 			} else {
1804 				if (nemo_icon_container_add (icon_container,
1805 								 NEMO_ICON_CONTAINER_ICON_DATA (file))) {
1806 					nemo_file_ref (file);
1807 				}
1808 			}
1809 		}
1810 
1811 		nemo_file_list_unref (files);
1812 		g_list_free (files);
1813 	}
1814 }
1815 
1816 static gboolean
nemo_icon_view_scroll_event(GtkWidget * widget,GdkEventScroll * scroll_event)1817 nemo_icon_view_scroll_event (GtkWidget *widget,
1818 			   GdkEventScroll *scroll_event)
1819 {
1820 	NemoIconView *icon_view;
1821 	GdkEvent *event_copy;
1822 	GdkEventScroll *scroll_event_copy;
1823 	gboolean ret;
1824 
1825 	icon_view = NEMO_ICON_VIEW (widget);
1826 
1827 	if (icon_view->details->compact &&
1828 	    (scroll_event->direction == GDK_SCROLL_UP ||
1829 	     scroll_event->direction == GDK_SCROLL_DOWN ||
1830 	     scroll_event->direction == GDK_SCROLL_SMOOTH)) {
1831 		ret = nemo_view_handle_scroll_event (NEMO_VIEW (icon_view), scroll_event);
1832 		if (!ret) {
1833 			/* in column-wise layout, re-emit vertical mouse scroll events as horizontal ones,
1834 			 * if they don't bump zoom */
1835 			event_copy = gdk_event_copy ((GdkEvent *) scroll_event);
1836 			scroll_event_copy = (GdkEventScroll *) event_copy;
1837 
1838 			/* transform vertical integer smooth scroll events into horizontal events */
1839 			if (scroll_event_copy->direction == GDK_SCROLL_SMOOTH &&
1840 				   scroll_event_copy->delta_x == 0) {
1841 				if (scroll_event_copy->delta_y == 1.0) {
1842 					scroll_event_copy->direction = GDK_SCROLL_DOWN;
1843 				} else if (scroll_event_copy->delta_y == -1.0) {
1844 					scroll_event_copy->direction = GDK_SCROLL_UP;
1845 				}
1846 			}
1847 
1848 			if (scroll_event_copy->direction == GDK_SCROLL_UP) {
1849 				scroll_event_copy->direction = GDK_SCROLL_LEFT;
1850 			} else if (scroll_event_copy->direction == GDK_SCROLL_DOWN) {
1851 				scroll_event_copy->direction = GDK_SCROLL_RIGHT;
1852 			}
1853 
1854 			ret = GTK_WIDGET_CLASS (nemo_icon_view_parent_class)->scroll_event (widget, scroll_event_copy);
1855 			gdk_event_free (event_copy);
1856 		}
1857 
1858 		return ret;
1859 	}
1860 
1861 	return GTK_WIDGET_CLASS (nemo_icon_view_parent_class)->scroll_event (widget, scroll_event);
1862 }
1863 
1864 static void
selection_changed_callback(NemoIconContainer * container,NemoIconView * icon_view)1865 selection_changed_callback (NemoIconContainer *container,
1866 			    NemoIconView *icon_view)
1867 {
1868 	g_assert (NEMO_IS_ICON_VIEW (icon_view));
1869 	g_assert (container == get_icon_container (icon_view));
1870 
1871 	nemo_view_notify_selection_changed (NEMO_VIEW (icon_view));
1872 }
1873 
1874 static void
icon_container_context_click_selection_callback(NemoIconContainer * container,GdkEventButton * event,NemoIconView * icon_view)1875 icon_container_context_click_selection_callback (NemoIconContainer *container,
1876 						 GdkEventButton *event,
1877 						 NemoIconView *icon_view)
1878 {
1879 	g_assert (NEMO_IS_ICON_CONTAINER (container));
1880 	g_assert (NEMO_IS_ICON_VIEW (icon_view));
1881 
1882 	nemo_view_pop_up_selection_context_menu
1883 		(NEMO_VIEW (icon_view), event);
1884 }
1885 
1886 static void
icon_container_context_click_background_callback(NemoIconContainer * container,GdkEventButton * event,NemoIconView * icon_view)1887 icon_container_context_click_background_callback (NemoIconContainer *container,
1888 						  GdkEventButton *event,
1889 						  NemoIconView *icon_view)
1890 {
1891 	g_assert (NEMO_IS_ICON_CONTAINER (container));
1892 	g_assert (NEMO_IS_ICON_VIEW (icon_view));
1893 
1894 	nemo_view_pop_up_background_context_menu
1895 		(NEMO_VIEW (icon_view), event);
1896 }
1897 
1898 static gboolean
nemo_icon_view_react_to_icon_change_idle_callback(gpointer data)1899 nemo_icon_view_react_to_icon_change_idle_callback (gpointer data)
1900 {
1901         NemoIconView *icon_view;
1902 
1903         g_assert (NEMO_IS_ICON_VIEW (data));
1904 
1905         icon_view = NEMO_ICON_VIEW (data);
1906         icon_view->details->react_to_icon_change_idle_id = 0;
1907 
1908 	/* Rebuild the menus since some of them (e.g. Restore Stretched Icons)
1909 	 * may be different now.
1910 	 */
1911 	nemo_view_update_menus (NEMO_VIEW (icon_view));
1912 
1913         /* Don't call this again (unless rescheduled) */
1914         return FALSE;
1915 }
1916 
1917 static void
icon_position_changed_callback(NemoIconContainer * container,NemoFile * file,const NemoIconPosition * position,NemoIconView * icon_view)1918 icon_position_changed_callback (NemoIconContainer *container,
1919 				NemoFile *file,
1920 				const NemoIconPosition *position,
1921 				NemoIconView *icon_view)
1922 {
1923 	char scale_string[G_ASCII_DTOSTR_BUF_SIZE];
1924 
1925 	g_assert (NEMO_IS_ICON_VIEW (icon_view));
1926 	g_assert (container == get_icon_container (icon_view));
1927 	g_assert (NEMO_IS_FILE (file));
1928 
1929 	/* Schedule updating menus for the next idle. Doing it directly here
1930 	 * noticeably slows down icon stretching.  The other work here to
1931 	 * store the icon position and scale does not seem to noticeably
1932 	 * slow down icon stretching. It would be trickier to move to an
1933 	 * idle call, because we'd have to keep track of potentially multiple
1934 	 * sets of file/geometry info.
1935 	 */
1936 	if (nemo_view_get_active (NEMO_VIEW (icon_view)) &&
1937 	    icon_view->details->react_to_icon_change_idle_id == 0) {
1938                 icon_view->details->react_to_icon_change_idle_id
1939                         = g_idle_add (nemo_icon_view_react_to_icon_change_idle_callback,
1940 				      icon_view);
1941 	}
1942 
1943 	/* Store the new position of the icon in the metadata. */
1944 	if (!nemo_file_get_is_desktop_orphan (file)) {
1945 		nemo_file_set_position (file, position->x, position->y);
1946         nemo_file_set_monitor_number (file, position->monitor);
1947 	}
1948 
1949 	g_ascii_dtostr (scale_string, sizeof (scale_string), position->scale);
1950 
1951     sync_directory_monitor_number (icon_view, file);
1952 
1953 	nemo_file_set_metadata (file, NEMO_METADATA_KEY_ICON_SCALE, "1.0", scale_string);
1954 }
1955 
1956 /* Attempt to change the filename to the new text.  Notify user if operation fails. */
1957 static void
icon_rename_ended_cb(NemoIconContainer * container,NemoFile * file,const char * new_name,NemoIconView * icon_view)1958 icon_rename_ended_cb (NemoIconContainer *container,
1959 		      NemoFile *file,
1960 		      const char *new_name,
1961 		      NemoIconView *icon_view)
1962 {
1963 	g_assert (NEMO_IS_FILE (file));
1964 
1965 	nemo_view_set_is_renaming (NEMO_VIEW (icon_view), FALSE);
1966 
1967 	/* Don't allow a rename with an empty string. Revert to original
1968 	 * without notifying the user.
1969 	 */
1970 	if ((new_name == NULL) || (new_name[0] == '\0')) {
1971 		return;
1972 	}
1973 
1974 	nemo_rename_file (file, new_name, NULL, NULL);
1975 }
1976 
1977 static void
icon_rename_started_cb(NemoIconContainer * container,GtkWidget * widget,gpointer callback_data)1978 icon_rename_started_cb (NemoIconContainer *container,
1979 			GtkWidget *widget,
1980 			gpointer callback_data)
1981 {
1982 	NemoView *directory_view;
1983 
1984 	directory_view = NEMO_VIEW (callback_data);
1985 	nemo_clipboard_set_up_editable
1986 		(GTK_EDITABLE (widget),
1987 		 nemo_view_get_ui_manager (directory_view),
1988 		 FALSE);
1989 }
1990 
1991 static char *
get_icon_uri_callback(NemoIconContainer * container,NemoFile * file,NemoIconView * icon_view)1992 get_icon_uri_callback (NemoIconContainer *container,
1993 		       NemoFile *file,
1994 		       NemoIconView *icon_view)
1995 {
1996 	g_assert (NEMO_IS_ICON_CONTAINER (container));
1997 	g_assert (NEMO_IS_FILE (file));
1998 	g_assert (NEMO_IS_ICON_VIEW (icon_view));
1999 
2000 	return nemo_file_get_uri (file);
2001 }
2002 
2003 static char *
get_icon_drop_target_uri_callback(NemoIconContainer * container,NemoFile * file,NemoIconView * icon_view)2004 get_icon_drop_target_uri_callback (NemoIconContainer *container,
2005 		       		   NemoFile *file,
2006 		       		   NemoIconView *icon_view)
2007 {
2008 	g_return_val_if_fail (NEMO_IS_ICON_CONTAINER (container), NULL);
2009 	g_return_val_if_fail (NEMO_IS_FILE (file), NULL);
2010 	g_return_val_if_fail (NEMO_IS_ICON_VIEW (icon_view), NULL);
2011 
2012 	return nemo_file_get_drop_target_uri (file);
2013 }
2014 
2015 /* Preferences changed callbacks */
2016 static void
nemo_icon_view_click_policy_changed(NemoView * directory_view)2017 nemo_icon_view_click_policy_changed (NemoView *directory_view)
2018 {
2019     g_assert (NEMO_IS_ICON_VIEW (directory_view));
2020 
2021     nemo_icon_view_update_click_mode (NEMO_ICON_VIEW (directory_view));
2022 }
2023 
2024 static void
nemo_icon_view_click_to_rename_mode_changed(NemoView * directory_view)2025 nemo_icon_view_click_to_rename_mode_changed (NemoView *directory_view)
2026 {
2027     g_assert (NEMO_IS_ICON_VIEW (directory_view));
2028 
2029     nemo_icon_view_update_click_to_rename_mode (NEMO_ICON_VIEW (directory_view));
2030 }
2031 
2032 static void
image_display_policy_changed_callback(gpointer callback_data)2033 image_display_policy_changed_callback (gpointer callback_data)
2034 {
2035 	NemoIconView *icon_view;
2036 
2037 	icon_view = NEMO_ICON_VIEW (callback_data);
2038 
2039 	nemo_icon_container_request_update_all (get_icon_container (icon_view));
2040 }
2041 
2042 static void
text_attribute_names_changed_callback(gpointer callback_data)2043 text_attribute_names_changed_callback (gpointer callback_data)
2044 {
2045 	NemoIconView *icon_view;
2046 
2047 	icon_view = NEMO_ICON_VIEW (callback_data);
2048 
2049 	nemo_icon_container_request_update_all (get_icon_container (icon_view));
2050 }
2051 
2052 static void
default_sort_order_changed_callback(gpointer callback_data)2053 default_sort_order_changed_callback (gpointer callback_data)
2054 {
2055 	NemoIconView *icon_view;
2056 	NemoFile *file;
2057 	char *sort_name;
2058 	NemoIconContainer *icon_container;
2059 
2060 	g_return_if_fail (NEMO_IS_ICON_VIEW (callback_data));
2061 
2062 	icon_view = NEMO_ICON_VIEW (callback_data);
2063 
2064 	file = nemo_view_get_directory_as_file (NEMO_VIEW (icon_view));
2065 	sort_name = nemo_icon_view_get_directory_sort_by (icon_view, file);
2066 	set_sort_criterion (icon_view, get_sort_criterion_by_metadata_text (sort_name), FALSE);
2067 	g_free (sort_name);
2068 
2069 	icon_container = get_icon_container (icon_view);
2070 	g_return_if_fail (NEMO_IS_ICON_CONTAINER (icon_container));
2071 
2072 	nemo_icon_container_request_update_all (icon_container);
2073 }
2074 
2075 static void
default_sort_in_reverse_order_changed_callback(gpointer callback_data)2076 default_sort_in_reverse_order_changed_callback (gpointer callback_data)
2077 {
2078 	NemoIconView *icon_view;
2079 	NemoFile *file;
2080 	NemoIconContainer *icon_container;
2081 
2082 	g_return_if_fail (NEMO_IS_ICON_VIEW (callback_data));
2083 
2084 	icon_view = NEMO_ICON_VIEW (callback_data);
2085 
2086 	file = nemo_view_get_directory_as_file (NEMO_VIEW (icon_view));
2087 	nemo_icon_view_set_sort_reversed (icon_view, nemo_icon_view_get_directory_sort_reversed (icon_view, file), FALSE);
2088 	icon_container = get_icon_container (icon_view);
2089 	g_return_if_fail (NEMO_IS_ICON_CONTAINER (icon_container));
2090 
2091 	nemo_icon_container_request_update_all (icon_container);
2092 }
2093 
2094 static void
default_zoom_level_changed_callback(gpointer callback_data)2095 default_zoom_level_changed_callback (gpointer callback_data)
2096 {
2097 	NemoIconView *icon_view;
2098 	NemoFile *file;
2099 	int level;
2100 
2101 	g_return_if_fail (NEMO_IS_ICON_VIEW (callback_data));
2102 
2103 	icon_view = NEMO_ICON_VIEW (callback_data);
2104 
2105 	if (nemo_view_supports_zooming (NEMO_VIEW (icon_view))) {
2106 		file = nemo_view_get_directory_as_file (NEMO_VIEW (icon_view));
2107 
2108         if (nemo_global_preferences_get_ignore_view_metadata () &&
2109             nemo_window_get_ignore_meta_zoom_level (nemo_view_get_nemo_window (NEMO_VIEW (icon_view))) > -1) {
2110             level = nemo_window_get_ignore_meta_zoom_level (nemo_view_get_nemo_window (NEMO_VIEW (icon_view)));
2111         } else {
2112             sync_directory_monitor_number (icon_view, file);
2113 
2114             if (nemo_icon_view_is_compact (icon_view)) {
2115                 level = nemo_file_get_integer_metadata (file,
2116                                                         NEMO_METADATA_KEY_COMPACT_VIEW_ZOOM_LEVEL,
2117                                                         get_default_zoom_level (icon_view));
2118             } else {
2119                 level = nemo_file_get_integer_metadata (file,
2120                                                         NEMO_METADATA_KEY_ICON_VIEW_ZOOM_LEVEL,
2121                                                         get_default_zoom_level (icon_view));
2122             }
2123         }
2124         nemo_view_zoom_to_level (NEMO_VIEW (icon_view), level);
2125     }
2126 }
2127 
2128 static void
labels_beside_icons_changed_callback(gpointer callback_data)2129 labels_beside_icons_changed_callback (gpointer callback_data)
2130 {
2131 	NemoIconView *icon_view;
2132 
2133 	g_return_if_fail (NEMO_IS_ICON_VIEW (callback_data));
2134 
2135 	icon_view = NEMO_ICON_VIEW (callback_data);
2136 
2137 	set_labels_beside_icons (icon_view);
2138 }
2139 
2140 static void
all_columns_same_width_changed_callback(gpointer callback_data)2141 all_columns_same_width_changed_callback (gpointer callback_data)
2142 {
2143 	NemoIconView *icon_view;
2144 
2145 	g_assert (NEMO_IS_ICON_VIEW (callback_data));
2146 
2147 	icon_view = NEMO_ICON_VIEW (callback_data);
2148 
2149 	set_columns_same_width (icon_view);
2150 }
2151 
2152 
2153 static void
nemo_icon_view_sort_directories_first_changed(NemoView * directory_view)2154 nemo_icon_view_sort_directories_first_changed (NemoView *directory_view)
2155 {
2156 	NemoIconView *icon_view;
2157 
2158 	icon_view = NEMO_ICON_VIEW (directory_view);
2159 
2160 	if (nemo_icon_view_using_auto_layout (icon_view)) {
2161 		nemo_icon_container_sort
2162 			(get_icon_container (icon_view));
2163 	}
2164 }
2165 
2166 static gboolean
icon_view_can_accept_item(NemoIconContainer * container,NemoFile * target_item,const char * item_uri,NemoView * view)2167 icon_view_can_accept_item (NemoIconContainer *container,
2168 			   NemoFile *target_item,
2169 			   const char *item_uri,
2170 			   NemoView *view)
2171 {
2172 	return nemo_drag_can_accept_item (target_item, item_uri);
2173 }
2174 
2175 static char *
icon_view_get_container_uri(NemoIconContainer * container,NemoView * view)2176 icon_view_get_container_uri (NemoIconContainer *container,
2177 			     NemoView *view)
2178 {
2179 	return nemo_view_get_uri (view);
2180 }
2181 
2182 static void
icon_view_move_copy_items(NemoIconContainer * container,const GList * item_uris,GArray * relative_item_points,const char * target_dir,int copy_action,int x,int y,NemoView * view)2183 icon_view_move_copy_items (NemoIconContainer *container,
2184 			   const GList *item_uris,
2185 			   GArray *relative_item_points,
2186 			   const char *target_dir,
2187 			   int copy_action,
2188 			   int x, int y,
2189 			   NemoView *view)
2190 {
2191 	nemo_clipboard_clear_if_colliding_uris (GTK_WIDGET (view),
2192 						    item_uris,
2193 						    nemo_view_get_copied_files_atom (view));
2194 	nemo_view_move_copy_items (view, item_uris, relative_item_points, target_dir,
2195 				       copy_action, x, y);
2196 }
2197 
2198 static void
nemo_icon_view_update_click_mode(NemoIconView * icon_view)2199 nemo_icon_view_update_click_mode (NemoIconView *icon_view)
2200 {
2201 	NemoIconContainer	*icon_container;
2202 	int			click_mode;
2203 
2204 	icon_container = get_icon_container (icon_view);
2205 	g_assert (icon_container != NULL);
2206 
2207 	click_mode = g_settings_get_enum (nemo_preferences, NEMO_PREFERENCES_CLICK_POLICY);
2208 
2209 	nemo_icon_container_set_single_click_mode (icon_container,
2210 						       click_mode == NEMO_CLICK_POLICY_SINGLE);
2211 }
2212 
2213 static void
nemo_icon_view_update_click_to_rename_mode(NemoIconView * icon_view)2214 nemo_icon_view_update_click_to_rename_mode (NemoIconView *icon_view)
2215 {
2216     NemoIconContainer   *icon_container;
2217     gboolean enabled;
2218 
2219     icon_container = get_icon_container (icon_view);
2220     g_assert (icon_container != NULL);
2221 
2222     enabled = g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_CLICK_TO_RENAME);
2223 
2224     nemo_icon_container_set_click_to_rename_enabled (icon_container,
2225                                                      enabled);
2226 }
2227 
2228 
2229 static gboolean
get_stored_layout_timestamp(NemoIconContainer * container,NemoIconData * icon_data,time_t * timestamp,NemoIconView * view)2230 get_stored_layout_timestamp (NemoIconContainer *container,
2231 			     NemoIconData *icon_data,
2232 			     time_t *timestamp,
2233 			     NemoIconView *view)
2234 {
2235 	NemoFile *file;
2236 	NemoDirectory *directory;
2237 
2238 	if (icon_data == NULL) {
2239 		directory = nemo_view_get_model (NEMO_VIEW (view));
2240 		if (directory == NULL) {
2241 			return FALSE;
2242 		}
2243 
2244 		file = nemo_directory_get_corresponding_file (directory);
2245 
2246         sync_directory_monitor_number (view, file);
2247 
2248         *timestamp = nemo_file_get_time_metadata (file, NEMO_METADATA_KEY_ICON_VIEW_LAYOUT_TIMESTAMP);
2249 
2250 		nemo_file_unref (file);
2251 	} else {
2252         sync_directory_monitor_number (view, NEMO_FILE (icon_data));
2253 
2254         *timestamp = nemo_file_get_time_metadata (NEMO_FILE (icon_data), NEMO_METADATA_KEY_ICON_POSITION_TIMESTAMP);
2255 	}
2256 
2257 	return TRUE;
2258 }
2259 
2260 static gboolean
store_layout_timestamp(NemoIconContainer * container,NemoIconData * icon_data,const time_t * timestamp,NemoIconView * view)2261 store_layout_timestamp (NemoIconContainer *container,
2262 			NemoIconData *icon_data,
2263 			const time_t *timestamp,
2264 			NemoIconView *view)
2265 {
2266 	NemoFile *file;
2267 	NemoDirectory *directory;
2268 
2269 	if (icon_data == NULL) {
2270 		directory = nemo_view_get_model (NEMO_VIEW (view));
2271 		if (directory == NULL) {
2272 			return FALSE;
2273 		}
2274 
2275 		file = nemo_directory_get_corresponding_file (directory);
2276 
2277         sync_directory_monitor_number (view, file);
2278 
2279 		nemo_file_set_time_metadata (file,
2280                                      NEMO_METADATA_KEY_ICON_VIEW_LAYOUT_TIMESTAMP,
2281                                      (time_t) *timestamp);
2282 		nemo_file_unref (file);
2283 	} else {
2284         sync_directory_monitor_number (view, NEMO_FILE (icon_data));
2285 
2286 		nemo_file_set_time_metadata (NEMO_FILE (icon_data),
2287                                      NEMO_METADATA_KEY_ICON_POSITION_TIMESTAMP,
2288                                      (time_t) *timestamp);
2289 	}
2290 
2291 	return TRUE;
2292 }
2293 
2294 static gboolean
focus_in_event_callback(GtkWidget * widget,GdkEventFocus * event,gpointer user_data)2295 focus_in_event_callback (GtkWidget *widget, GdkEventFocus *event, gpointer user_data)
2296 {
2297 	NemoWindowSlot *slot;
2298 	NemoIconView *icon_view = NEMO_ICON_VIEW (user_data);
2299 
2300 	/* make the corresponding slot (and the pane that contains it) active */
2301 	slot = nemo_view_get_nemo_window_slot (NEMO_VIEW (icon_view));
2302 	nemo_window_slot_make_hosting_pane_active (slot);
2303 
2304 	return FALSE;
2305 }
2306 
2307 static gboolean
button_press_callback(GtkWidget * widget,GdkEventFocus * event,gpointer user_data)2308 button_press_callback (GtkWidget *widget, GdkEventFocus *event, gpointer user_data)
2309 {
2310     NemoView *view = NEMO_VIEW (user_data);
2311     GdkEventButton *event_button = (GdkEventButton *)event;
2312     int selection_count;
2313 
2314     if (!nemo_view_get_active (view)) {
2315         NemoWindowSlot *slot = nemo_view_get_nemo_window_slot (view);
2316         nemo_window_slot_make_hosting_pane_active (slot);
2317         return TRUE;
2318     }
2319 
2320     /* double left click on blank will go to parent folder */
2321     if (g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_CLICK_DOUBLE_PARENT_FOLDER) &&
2322         (event_button->button == 1) && (event_button->type == GDK_2BUTTON_PRESS)) {
2323         selection_count = nemo_view_get_selection_count (NEMO_VIEW (view));
2324         if (selection_count == 0) {
2325             NemoWindowSlot *slot = nemo_view_get_nemo_window_slot (view);
2326             nemo_window_slot_go_up (slot, 0);
2327             return TRUE;
2328         }
2329     }
2330 
2331     return FALSE;
2332 }
2333 
2334 static NemoIconContainer *
create_icon_container(NemoIconView * icon_view)2335 create_icon_container (NemoIconView *icon_view)
2336 {
2337 	NemoIconContainer *icon_container;
2338 
2339     if (NEMO_ICON_VIEW_GET_CLASS (icon_view)->use_grid_container) {
2340         icon_container = nemo_icon_view_grid_container_new (icon_view,
2341                                                             icon_view->details->is_desktop);
2342     } else {
2343         icon_container = nemo_icon_view_container_new (icon_view,
2344                                                        icon_view->details->is_desktop);
2345     }
2346 
2347 	icon_view->details->icon_container = GTK_WIDGET (icon_container);
2348 	g_object_add_weak_pointer (G_OBJECT (icon_container),
2349 				   (gpointer *) &icon_view->details->icon_container);
2350 
2351 	gtk_widget_set_can_focus (GTK_WIDGET (icon_container), TRUE);
2352 
2353     g_signal_connect_object (icon_container, "button_press_event",
2354                  G_CALLBACK (button_press_callback), icon_view, 0);
2355 	g_signal_connect_object (icon_container, "focus_in_event",
2356 				 G_CALLBACK (focus_in_event_callback), icon_view, 0);
2357 	g_signal_connect_object (icon_container, "activate",
2358 				 G_CALLBACK (icon_container_activate_callback), icon_view, 0);
2359 	g_signal_connect_object (icon_container, "activate_alternate",
2360 				 G_CALLBACK (icon_container_activate_alternate_callback), icon_view, 0);
2361 	g_signal_connect_object (icon_container, "activate_previewer",
2362 				 G_CALLBACK (icon_container_activate_previewer_callback), icon_view, 0);
2363 	g_signal_connect_object (icon_container, "band_select_started",
2364 				 G_CALLBACK (band_select_started_callback), icon_view, 0);
2365 	g_signal_connect_object (icon_container, "band_select_ended",
2366 				 G_CALLBACK (band_select_ended_callback), icon_view, 0);
2367 	g_signal_connect_object (icon_container, "context_click_selection",
2368 				 G_CALLBACK (icon_container_context_click_selection_callback), icon_view, 0);
2369 	g_signal_connect_object (icon_container, "context_click_background",
2370 				 G_CALLBACK (icon_container_context_click_background_callback), icon_view, 0);
2371 	g_signal_connect_object (icon_container, "icon_position_changed",
2372 				 G_CALLBACK (icon_position_changed_callback), icon_view, 0);
2373 	g_signal_connect_object (icon_container, "selection_changed",
2374 				 G_CALLBACK (selection_changed_callback), icon_view, 0);
2375 	/* FIXME: many of these should move into fm-icon-container as virtual methods */
2376 	g_signal_connect_object (icon_container, "get_icon_uri",
2377 				 G_CALLBACK (get_icon_uri_callback), icon_view, 0);
2378 	g_signal_connect_object (icon_container, "get_icon_drop_target_uri",
2379 				 G_CALLBACK (get_icon_drop_target_uri_callback), icon_view, 0);
2380 	g_signal_connect_object (icon_container, "move_copy_items",
2381 				 G_CALLBACK (icon_view_move_copy_items), icon_view, 0);
2382 	g_signal_connect_object (icon_container, "get_container_uri",
2383 				 G_CALLBACK (icon_view_get_container_uri), icon_view, 0);
2384 	g_signal_connect_object (icon_container, "can_accept_item",
2385 				 G_CALLBACK (icon_view_can_accept_item), icon_view, 0);
2386 	g_signal_connect_object (icon_container, "layout_changed",
2387 				 G_CALLBACK (layout_changed_callback), icon_view, 0);
2388 	g_signal_connect_object (icon_container, "icon_rename_started",
2389 				 G_CALLBACK (icon_rename_started_cb), icon_view, 0);
2390 	g_signal_connect_object (icon_container, "icon_rename_ended",
2391 				 G_CALLBACK (icon_rename_ended_cb), icon_view, 0);
2392 	g_signal_connect_object (icon_container, "icon_stretch_started",
2393 				 G_CALLBACK (nemo_view_update_menus), icon_view,
2394 				 G_CONNECT_SWAPPED);
2395 	g_signal_connect_object (icon_container, "icon_stretch_ended",
2396 				 G_CALLBACK (nemo_view_update_menus), icon_view,
2397 				 G_CONNECT_SWAPPED);
2398 
2399 	g_signal_connect_object (icon_container, "get_stored_layout_timestamp",
2400 				 G_CALLBACK (get_stored_layout_timestamp), icon_view, 0);
2401 	g_signal_connect_object (icon_container, "store_layout_timestamp",
2402 				 G_CALLBACK (store_layout_timestamp), icon_view, 0);
2403 
2404 	gtk_container_add (GTK_CONTAINER (icon_view),
2405 			   GTK_WIDGET (icon_container));
2406 
2407 	nemo_icon_view_update_click_mode (icon_view);
2408     nemo_icon_view_update_click_to_rename_mode (icon_view);
2409 
2410 	gtk_widget_show (GTK_WIDGET (icon_container));
2411 
2412 	return icon_container;
2413 }
2414 
2415 /* Handles an URL received from Mozilla */
2416 static void
icon_view_handle_netscape_url(NemoIconContainer * container,const char * encoded_url,const char * target_uri,GdkDragAction action,int x,int y,NemoIconView * view)2417 icon_view_handle_netscape_url (NemoIconContainer *container, const char *encoded_url,
2418 			       const char *target_uri,
2419 			       GdkDragAction action, int x, int y, NemoIconView *view)
2420 {
2421 	nemo_view_handle_netscape_url_drop (NEMO_VIEW (view),
2422 						encoded_url, target_uri, action, x, y);
2423 }
2424 
2425 static void
icon_view_handle_uri_list(NemoIconContainer * container,const char * item_uris,const char * target_uri,GdkDragAction action,int x,int y,NemoIconView * view)2426 icon_view_handle_uri_list (NemoIconContainer *container, const char *item_uris,
2427 			   const char *target_uri,
2428 			   GdkDragAction action, int x, int y, NemoIconView *view)
2429 {
2430 	nemo_view_handle_uri_list_drop (NEMO_VIEW (view),
2431 					    item_uris, target_uri, action, x, y);
2432 }
2433 
2434 static void
icon_view_handle_text(NemoIconContainer * container,const char * text,const char * target_uri,GdkDragAction action,int x,int y,NemoIconView * view)2435 icon_view_handle_text (NemoIconContainer *container, const char *text,
2436 		       const char *target_uri,
2437 		       GdkDragAction action, int x, int y, NemoIconView *view)
2438 {
2439 	nemo_view_handle_text_drop (NEMO_VIEW (view),
2440 					text, target_uri, action, x, y);
2441 }
2442 
2443 static void
icon_view_handle_raw(NemoIconContainer * container,const char * raw_data,int length,const char * target_uri,const char * direct_save_uri,GdkDragAction action,int x,int y,NemoIconView * view)2444 icon_view_handle_raw (NemoIconContainer *container, const char *raw_data,
2445 		      int length, const char *target_uri, const char *direct_save_uri,
2446 		      GdkDragAction action, int x, int y, NemoIconView *view)
2447 {
2448 	nemo_view_handle_raw_drop (NEMO_VIEW (view),
2449 				       raw_data, length, target_uri, direct_save_uri, action, x, y);
2450 }
2451 
2452 static char *
icon_view_get_first_visible_file(NemoView * view)2453 icon_view_get_first_visible_file (NemoView *view)
2454 {
2455 	NemoFile *file;
2456 	NemoIconView *icon_view;
2457 
2458 	icon_view = NEMO_ICON_VIEW (view);
2459 
2460 	file = NEMO_FILE (nemo_icon_container_get_first_visible_icon (get_icon_container (icon_view)));
2461 
2462 	if (file) {
2463 		return nemo_file_get_uri (file);
2464 	}
2465 
2466 	return NULL;
2467 }
2468 
2469 static void
icon_view_scroll_to_file(NemoView * view,const char * uri)2470 icon_view_scroll_to_file (NemoView *view,
2471 			  const char *uri)
2472 {
2473 	NemoFile *file;
2474 	NemoIconView *icon_view;
2475 
2476 	icon_view = NEMO_ICON_VIEW (view);
2477 
2478 	if (uri != NULL) {
2479 		/* Only if existing, since we don't want to add the file to
2480 		   the directory if it has been removed since then */
2481 		file = nemo_file_get_existing_by_uri (uri);
2482 		if (file != NULL) {
2483 			nemo_icon_container_scroll_to_icon (get_icon_container (icon_view),
2484 								NEMO_ICON_CONTAINER_ICON_DATA (file));
2485 			nemo_file_unref (file);
2486 		}
2487 	}
2488 }
2489 
2490 static const char *
nemo_icon_view_get_id(NemoView * view)2491 nemo_icon_view_get_id (NemoView *view)
2492 {
2493 	if (nemo_icon_view_is_compact (NEMO_ICON_VIEW (view))) {
2494 		return FM_COMPACT_VIEW_ID;
2495 	}
2496 
2497 	return NEMO_ICON_VIEW_ID;
2498 }
2499 
2500 static void
set_compact_view(NemoIconView * icon_view,gboolean compact)2501 set_compact_view (NemoIconView *icon_view,
2502                   gboolean      compact)
2503 {
2504     icon_view->details->compact = compact;
2505 
2506     if (compact) {
2507         nemo_icon_container_set_layout_mode (get_icon_container (icon_view),
2508                                              gtk_widget_get_direction (GTK_WIDGET(icon_view)) == GTK_TEXT_DIR_RTL ?
2509                                                                                                      NEMO_ICON_LAYOUT_T_B_R_L :
2510                                                                                                      NEMO_ICON_LAYOUT_T_B_L_R);
2511         nemo_icon_container_set_forced_icon_size (get_icon_container (icon_view),
2512                                                   NEMO_COMPACT_FORCED_ICON_SIZE);
2513     } else {
2514         nemo_icon_container_set_layout_mode (get_icon_container (icon_view),
2515                                              gtk_widget_get_direction (GTK_WIDGET(icon_view)) == GTK_TEXT_DIR_RTL ?
2516                                                                                                      NEMO_ICON_LAYOUT_R_L_T_B :
2517                                                                                                      NEMO_ICON_LAYOUT_L_R_T_B);
2518         nemo_icon_container_set_forced_icon_size (get_icon_container (icon_view),
2519                                                   0);
2520     }
2521 }
2522 
2523 static void
nemo_icon_view_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)2524 nemo_icon_view_set_property (GObject         *object,
2525 			   guint            prop_id,
2526 			   const GValue    *value,
2527 			   GParamSpec      *pspec)
2528 {
2529 	NemoIconView *icon_view;
2530 
2531 	icon_view = NEMO_ICON_VIEW (object);
2532 
2533 	switch (prop_id)  {
2534 	case PROP_COMPACT:
2535         set_compact_view (icon_view, g_value_get_boolean (value));
2536 		break;
2537 	case PROP_SUPPORTS_AUTO_LAYOUT:
2538 		icon_view->details->supports_auto_layout = g_value_get_boolean (value);
2539 		break;
2540 	case PROP_IS_DESKTOP:
2541 		icon_view->details->is_desktop = g_value_get_boolean (value);
2542 		break;
2543 	case PROP_SUPPORTS_KEEP_ALIGNED:
2544 		icon_view->details->supports_keep_aligned = g_value_get_boolean (value);
2545 		break;
2546 	case PROP_SUPPORTS_LABELS_BESIDE_ICONS:
2547 		icon_view->details->supports_labels_beside_icons = g_value_get_boolean (value);
2548 		break;
2549 	default:
2550 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2551 		break;
2552 	}
2553 }
2554 
2555 static void
nemo_icon_view_finalize(GObject * object)2556 nemo_icon_view_finalize (GObject *object)
2557 {
2558 	NemoIconView *icon_view;
2559 
2560 	icon_view = NEMO_ICON_VIEW (object);
2561 
2562 	g_free (icon_view->details);
2563 
2564 	g_signal_handlers_disconnect_by_func (nemo_preferences,
2565 					      default_sort_order_changed_callback,
2566 					      icon_view);
2567 	g_signal_handlers_disconnect_by_func (nemo_preferences,
2568 					      default_sort_in_reverse_order_changed_callback,
2569 					      icon_view);
2570 	g_signal_handlers_disconnect_by_func (nemo_preferences,
2571 					      image_display_policy_changed_callback,
2572 					      icon_view);
2573 
2574 	g_signal_handlers_disconnect_by_func (nemo_icon_view_preferences,
2575 					      default_zoom_level_changed_callback,
2576 					      icon_view);
2577 	g_signal_handlers_disconnect_by_func (nemo_icon_view_preferences,
2578 					      labels_beside_icons_changed_callback,
2579 					      icon_view);
2580 	g_signal_handlers_disconnect_by_func (nemo_icon_view_preferences,
2581 					      text_attribute_names_changed_callback,
2582 					      icon_view);
2583 
2584 	g_signal_handlers_disconnect_by_func (nemo_compact_view_preferences,
2585 					      default_zoom_level_changed_callback,
2586 					      icon_view);
2587 	g_signal_handlers_disconnect_by_func (nemo_compact_view_preferences,
2588 					      all_columns_same_width_changed_callback,
2589 					      icon_view);
2590 
2591 	G_OBJECT_CLASS (nemo_icon_view_parent_class)->finalize (object);
2592 }
2593 
2594 static void
nemo_icon_view_constructed(GObject * object)2595 nemo_icon_view_constructed (GObject *object)
2596 {
2597     NemoIconView *icon_view;
2598     NemoIconContainer *icon_container;
2599 
2600     icon_view = NEMO_ICON_VIEW (object);
2601 
2602     G_OBJECT_CLASS (nemo_icon_view_parent_class)->constructed (G_OBJECT (icon_view));
2603 
2604     g_return_if_fail (gtk_bin_get_child (GTK_BIN (icon_view)) == NULL);
2605 
2606     icon_container = create_icon_container (icon_view);
2607 
2608     /* Set our default layout mode */
2609     if (!icon_view->details->is_desktop) {
2610         nemo_icon_container_set_layout_mode (icon_container,
2611                                              gtk_widget_get_direction (GTK_WIDGET(icon_container)) == GTK_TEXT_DIR_RTL ?
2612                                              NEMO_ICON_LAYOUT_R_L_T_B :
2613                                              NEMO_ICON_LAYOUT_L_R_T_B);
2614     }
2615 
2616     g_signal_connect_swapped (nemo_preferences,
2617                   "changed::" NEMO_PREFERENCES_DEFAULT_SORT_ORDER,
2618                   G_CALLBACK (default_sort_order_changed_callback),
2619                   icon_view);
2620     g_signal_connect_swapped (nemo_preferences,
2621                   "changed::" NEMO_PREFERENCES_DEFAULT_SORT_IN_REVERSE_ORDER,
2622                   G_CALLBACK (default_sort_in_reverse_order_changed_callback),
2623                   icon_view);
2624     g_signal_connect_swapped (nemo_preferences,
2625                   "changed::" NEMO_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS,
2626                   G_CALLBACK (image_display_policy_changed_callback),
2627                   icon_view);
2628     g_signal_connect_swapped (nemo_icon_view_preferences,
2629                   "changed::" NEMO_PREFERENCES_ICON_VIEW_DEFAULT_ZOOM_LEVEL,
2630                   G_CALLBACK (default_zoom_level_changed_callback),
2631                   icon_view);
2632     g_signal_connect_swapped (nemo_icon_view_preferences,
2633                   "changed::" NEMO_PREFERENCES_ICON_VIEW_LABELS_BESIDE_ICONS,
2634                   G_CALLBACK (labels_beside_icons_changed_callback),
2635                   icon_view);
2636     g_signal_connect_swapped (nemo_icon_view_preferences,
2637                   "changed::" NEMO_PREFERENCES_ICON_VIEW_CAPTIONS,
2638                   G_CALLBACK (text_attribute_names_changed_callback),
2639                   icon_view);
2640 
2641     g_signal_connect_swapped (nemo_compact_view_preferences,
2642                   "changed::" NEMO_PREFERENCES_COMPACT_VIEW_DEFAULT_ZOOM_LEVEL,
2643                   G_CALLBACK (default_zoom_level_changed_callback),
2644                   icon_view);
2645     g_signal_connect_swapped (nemo_compact_view_preferences,
2646                   "changed::" NEMO_PREFERENCES_COMPACT_VIEW_ALL_COLUMNS_SAME_WIDTH,
2647                   G_CALLBACK (all_columns_same_width_changed_callback),
2648                   icon_view);
2649 
2650     g_signal_connect_object (get_icon_container (icon_view), "handle_netscape_url",
2651                  G_CALLBACK (icon_view_handle_netscape_url), icon_view, 0);
2652     g_signal_connect_object (get_icon_container (icon_view), "handle_uri_list",
2653                  G_CALLBACK (icon_view_handle_uri_list), icon_view, 0);
2654     g_signal_connect_object (get_icon_container (icon_view), "handle_text",
2655                  G_CALLBACK (icon_view_handle_text), icon_view, 0);
2656     g_signal_connect_object (get_icon_container (icon_view), "handle_raw",
2657                  G_CALLBACK (icon_view_handle_raw), icon_view, 0);
2658 
2659     icon_view->details->clipboard_handler_id =
2660         g_signal_connect (nemo_clipboard_monitor_get (),
2661                           "clipboard_info",
2662                           G_CALLBACK (icon_view_notify_clipboard_info), icon_view);
2663 
2664     nemo_icon_container_set_is_desktop (icon_container, FALSE);
2665 }
2666 
2667 static void
nemo_icon_view_class_init(NemoIconViewClass * klass)2668 nemo_icon_view_class_init (NemoIconViewClass *klass)
2669 {
2670 	NemoViewClass *nemo_view_class;
2671 	GObjectClass *oclass;
2672 
2673     klass->use_grid_container = FALSE;
2674 
2675 	nemo_view_class = NEMO_VIEW_CLASS (klass);
2676 	oclass = G_OBJECT_CLASS (klass);
2677 
2678 	oclass->set_property = nemo_icon_view_set_property;
2679 	oclass->finalize = nemo_icon_view_finalize;
2680     oclass->constructed = nemo_icon_view_constructed;
2681 
2682 	GTK_WIDGET_CLASS (klass)->destroy = nemo_icon_view_destroy;
2683 	GTK_WIDGET_CLASS (klass)->screen_changed = nemo_icon_view_screen_changed;
2684 	GTK_WIDGET_CLASS (klass)->scroll_event = nemo_icon_view_scroll_event;
2685 
2686 	nemo_view_class->add_file = nemo_icon_view_add_file;
2687 	nemo_view_class->begin_loading = nemo_icon_view_begin_loading;
2688 	nemo_view_class->bump_zoom_level = nemo_icon_view_bump_zoom_level;
2689 	nemo_view_class->can_rename_file = nemo_icon_view_can_rename_file;
2690 	nemo_view_class->can_zoom_in = nemo_icon_view_can_zoom_in;
2691 	nemo_view_class->can_zoom_out = nemo_icon_view_can_zoom_out;
2692 	nemo_view_class->clear = nemo_icon_view_clear;
2693 	nemo_view_class->end_loading = nemo_icon_view_end_loading;
2694 	nemo_view_class->file_changed = nemo_icon_view_file_changed;
2695 	nemo_view_class->get_selected_icon_locations = nemo_icon_view_get_selected_icon_locations;
2696     nemo_view_class->get_selection = nemo_icon_view_get_selection;
2697     nemo_view_class->peek_selection = nemo_icon_view_peek_selection;
2698 	nemo_view_class->get_selection_count = nemo_icon_view_get_selection_count;
2699 	nemo_view_class->get_selection_for_file_transfer = nemo_icon_view_get_selection;
2700 	nemo_view_class->get_item_count = nemo_icon_view_get_item_count;
2701 	nemo_view_class->is_empty = nemo_icon_view_is_empty;
2702 	nemo_view_class->remove_file = nemo_icon_view_remove_file;
2703 	nemo_view_class->reset_to_defaults = nemo_icon_view_reset_to_defaults;
2704 	nemo_view_class->restore_default_zoom_level = nemo_icon_view_restore_default_zoom_level;
2705     nemo_view_class->get_default_zoom_level = nemo_icon_view_get_default_zoom_level;
2706 	nemo_view_class->reveal_selection = nemo_icon_view_reveal_selection;
2707 	nemo_view_class->select_all = nemo_icon_view_select_all;
2708 	nemo_view_class->set_selection = nemo_icon_view_set_selection;
2709 	nemo_view_class->invert_selection = nemo_icon_view_invert_selection;
2710 	nemo_view_class->compare_files = compare_files;
2711 	nemo_view_class->zoom_to_level = nemo_icon_view_zoom_to_level;
2712 	nemo_view_class->get_zoom_level = nemo_icon_view_get_zoom_level;
2713         nemo_view_class->click_policy_changed = nemo_icon_view_click_policy_changed;
2714         nemo_view_class->click_to_rename_mode_changed = nemo_icon_view_click_to_rename_mode_changed;
2715         nemo_view_class->merge_menus = nemo_icon_view_merge_menus;
2716         nemo_view_class->unmerge_menus = nemo_icon_view_unmerge_menus;
2717         nemo_view_class->sort_directories_first_changed = nemo_icon_view_sort_directories_first_changed;
2718         nemo_view_class->start_renaming_file = nemo_icon_view_start_renaming_file;
2719         nemo_view_class->update_menus = nemo_icon_view_update_menus;
2720 	nemo_view_class->using_manual_layout = nemo_icon_view_using_manual_layout;
2721 	nemo_view_class->widget_to_file_operation_position = nemo_icon_view_widget_to_file_operation_position;
2722 	nemo_view_class->get_view_id = nemo_icon_view_get_id;
2723 	nemo_view_class->get_first_visible_file = icon_view_get_first_visible_file;
2724 	nemo_view_class->scroll_to_file = icon_view_scroll_to_file;
2725 
2726 	properties[PROP_COMPACT] =
2727 		g_param_spec_boolean ("compact",
2728 				      "Compact",
2729 				      "Whether this view provides a compact listing",
2730 				      FALSE,
2731 				      G_PARAM_WRITABLE);
2732 	properties[PROP_SUPPORTS_AUTO_LAYOUT] =
2733 		g_param_spec_boolean ("supports-auto-layout",
2734 				      "Supports auto layout",
2735 				      "Whether this view supports auto layout",
2736 				      TRUE,
2737 				      G_PARAM_WRITABLE |
2738 				      G_PARAM_CONSTRUCT_ONLY);
2739 	properties[PROP_IS_DESKTOP] =
2740 		g_param_spec_boolean ("is-desktop",
2741 				      "Is a desktop view",
2742 				      "Whether this view is on a desktop",
2743 				      FALSE,
2744 				      G_PARAM_WRITABLE |
2745 				      G_PARAM_CONSTRUCT_ONLY);
2746 	properties[PROP_SUPPORTS_KEEP_ALIGNED] =
2747 		g_param_spec_boolean ("supports-keep-aligned",
2748 				      "Supports keep aligned",
2749 				      "Whether this view supports keep aligned",
2750 				      FALSE,
2751 				      G_PARAM_WRITABLE |
2752 				      G_PARAM_CONSTRUCT_ONLY);
2753 	properties[PROP_SUPPORTS_LABELS_BESIDE_ICONS] =
2754 		g_param_spec_boolean ("supports-labels-beside-icons",
2755 				      "Supports labels beside icons",
2756 				      "Whether this view supports labels beside icons",
2757 				      TRUE,
2758 				      G_PARAM_WRITABLE |
2759 				      G_PARAM_CONSTRUCT_ONLY);
2760 
2761 	g_object_class_install_properties (oclass, NUM_PROPERTIES, properties);
2762 }
2763 
2764 static void
nemo_icon_view_init(NemoIconView * icon_view)2765 nemo_icon_view_init (NemoIconView *icon_view)
2766 {
2767     icon_view->details = g_new0 (NemoIconViewDetails, 1);
2768     icon_view->details->sort = &sort_criteria[0];
2769 }
2770 
2771 static NemoView *
nemo_icon_view_create(NemoWindowSlot * slot)2772 nemo_icon_view_create (NemoWindowSlot *slot)
2773 {
2774 	NemoIconView *view;
2775 
2776 	view = g_object_new (NEMO_TYPE_ICON_VIEW,
2777 			     "window-slot", slot,
2778 			     NULL);
2779 #if GTK_CHECK_VERSION (3, 20, 0)
2780 	gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET(view)), GTK_STYLE_CLASS_VIEW);
2781 #endif
2782 
2783     set_compact_view (view, FALSE);
2784 
2785 	return NEMO_VIEW (view);
2786 }
2787 
2788 static NemoView *
nemo_compact_view_create(NemoWindowSlot * slot)2789 nemo_compact_view_create (NemoWindowSlot *slot)
2790 {
2791 	NemoIconView *view;
2792 
2793 	view = g_object_new (NEMO_TYPE_ICON_VIEW,
2794 			     "window-slot", slot,
2795 			     NULL);
2796 #if GTK_CHECK_VERSION (3, 20, 0)
2797 	gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET(view)), GTK_STYLE_CLASS_VIEW);
2798 #endif
2799 
2800     set_compact_view (view, TRUE);
2801 
2802     return NEMO_VIEW (view);
2803 }
2804 
2805 static gboolean
nemo_icon_view_supports_uri(const char * uri,GFileType file_type,const char * mime_type)2806 nemo_icon_view_supports_uri (const char *uri,
2807 			   GFileType file_type,
2808 			   const char *mime_type)
2809 {
2810 	if (file_type == G_FILE_TYPE_DIRECTORY) {
2811 		return TRUE;
2812 	}
2813 	if (strcmp (mime_type, NEMO_SAVED_SEARCH_MIMETYPE) == 0){
2814 		return TRUE;
2815 	}
2816 	if (g_str_has_prefix (uri, "trash:")) {
2817 		return TRUE;
2818 	}
2819 	if (g_str_has_prefix (uri, EEL_SEARCH_URI)) {
2820 		return TRUE;
2821 	}
2822 
2823 	return FALSE;
2824 }
2825 
2826 #define TRANSLATE_VIEW_INFO(view_info)					\
2827 	view_info.view_combo_label = _(view_info.view_combo_label);	\
2828 	view_info.view_menu_label_with_mnemonic = _(view_info.view_menu_label_with_mnemonic); \
2829 	view_info.error_label = _(view_info.error_label);		\
2830 	view_info.startup_error_label = _(view_info.startup_error_label); \
2831 	view_info.display_location_label = _(view_info.display_location_label); \
2832 
2833 
2834 static NemoViewInfo nemo_icon_view = {
2835 	(char *)NEMO_ICON_VIEW_ID,
2836 	/* translators: this is used in the view selection dropdown
2837 	 * of navigation windows and in the preferences dialog */
2838 	(char *)N_("Icon View"),
2839 	/* translators: this is used in the view menu */
2840 	(char *)N_("_Icons"),
2841 	(char *)N_("The icon view encountered an error."),
2842 	(char *)N_("The icon view encountered an error while starting up."),
2843 	(char *)N_("Display this location with the icon view."),
2844 	nemo_icon_view_create,
2845 	nemo_icon_view_supports_uri
2846 };
2847 
2848 static NemoViewInfo nemo_compact_view = {
2849 	(char *)FM_COMPACT_VIEW_ID,
2850 	/* translators: this is used in the view selection dropdown
2851 	 * of navigation windows and in the preferences dialog */
2852 	(char *)N_("Compact View"),
2853 	/* translators: this is used in the view menu */
2854 	(char *)N_("_Compact"),
2855 	(char *)N_("The compact view encountered an error."),
2856 	(char *)N_("The compact view encountered an error while starting up."),
2857 	(char *)N_("Display this location with the compact view."),
2858 	nemo_compact_view_create,
2859 	nemo_icon_view_supports_uri
2860 };
2861 
2862 gboolean
nemo_icon_view_is_compact(NemoIconView * view)2863 nemo_icon_view_is_compact (NemoIconView *view)
2864 {
2865 	return view->details->compact;
2866 }
2867 
2868 void
nemo_icon_view_register(void)2869 nemo_icon_view_register (void)
2870 {
2871 	TRANSLATE_VIEW_INFO (nemo_icon_view)
2872 		nemo_view_factory_register (&nemo_icon_view);
2873 }
2874 
2875 void
nemo_icon_view_compact_register(void)2876 nemo_icon_view_compact_register (void)
2877 {
2878 	TRANSLATE_VIEW_INFO (nemo_compact_view)
2879 		nemo_view_factory_register (&nemo_compact_view);
2880 }
2881 
2882