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