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 Mate 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 Mate 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 Mate Library; see the file COPYING.LIB. If not,
19 write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21
22 Authors: John Sullivan <sullivan@eazel.com>
23 */
24
25 #include <config.h>
26 #include <stdlib.h>
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <locale.h>
30 #include <signal.h>
31 #include <stdio.h>
32 #include <unistd.h>
33
34 #include <gtk/gtk.h>
35 #include <glib/gi18n.h>
36 #include <gio/gio.h>
37 #include <sys/types.h>
38 #include <sys/wait.h>
39
40 #include <eel/eel-background.h>
41 #include <eel/eel-glib-extensions.h>
42 #include <eel/eel-gtk-extensions.h>
43 #include <eel/eel-gtk-macros.h>
44 #include <eel/eel-stock-dialogs.h>
45 #include <eel/eel-string.h>
46 #include <eel/eel-vfs-extensions.h>
47
48 #include <libcaja-private/caja-clipboard-monitor.h>
49 #include <libcaja-private/caja-directory-background.h>
50 #include <libcaja-private/caja-directory.h>
51 #include <libcaja-private/caja-dnd.h>
52 #include <libcaja-private/caja-file-utilities.h>
53 #include <libcaja-private/caja-ui-utilities.h>
54 #include <libcaja-private/caja-global-preferences.h>
55 #include <libcaja-private/caja-icon-container.h>
56 #include <libcaja-private/caja-icon-dnd.h>
57 #include <libcaja-private/caja-link.h>
58 #include <libcaja-private/caja-metadata.h>
59 #include <libcaja-private/caja-view-factory.h>
60 #include <libcaja-private/caja-clipboard.h>
61 #include <libcaja-private/caja-desktop-icon-file.h>
62
63 #include "fm-icon-view.h"
64 #include "fm-actions.h"
65 #include "fm-icon-container.h"
66 #include "fm-desktop-icon-view.h"
67 #include "fm-error-reporting.h"
68 #include "caja-audio-mime-types.h"
69
70 #define POPUP_PATH_ICON_APPEARANCE "/selection/Icon Appearance Items"
71
72 enum
73 {
74 PROP_0,
75 PROP_COMPACT
76 };
77
78 typedef struct
79 {
80 const CajaFileSortType sort_type;
81 const char *metadata_text;
82 const char *action;
83 const char *menu_label;
84 const char *menu_hint;
85 } SortCriterion;
86
87 typedef enum
88 {
89 MENU_ITEM_TYPE_STANDARD,
90 MENU_ITEM_TYPE_CHECK,
91 MENU_ITEM_TYPE_RADIO,
92 MENU_ITEM_TYPE_TREE
93 } MenuItemType;
94
95 struct FMIconViewDetails
96 {
97 GList *icons_not_positioned;
98
99 guint react_to_icon_change_idle_id;
100
101 const SortCriterion *sort;
102 gboolean sort_reversed;
103
104 GtkActionGroup *icon_action_group;
105 guint icon_merge_id;
106
107 int audio_preview_timeout;
108 CajaFile *audio_preview_file;
109 int audio_preview_child_watch;
110 GPid audio_preview_child_pid;
111
112 gboolean filter_by_screen;
113
114 gboolean compact;
115
116 gulong clipboard_handler_id;
117 };
118
119
120 /* Note that the first item in this list is the default sort,
121 * and that the items show up in the menu in the order they
122 * appear in this list.
123 */
124 static const SortCriterion sort_criteria[] =
125 {
126 {
127 CAJA_FILE_SORT_BY_DISPLAY_NAME,
128 "name",
129 "Sort by Name",
130 N_("by _Name"),
131 N_("Keep icons sorted by name in rows")
132 },
133 {
134 CAJA_FILE_SORT_BY_SIZE,
135 "size",
136 "Sort by Size",
137 N_("by _Size"),
138 N_("Keep icons sorted by size in rows")
139 },
140 {
141 CAJA_FILE_SORT_BY_SIZE_ON_DISK,
142 "size_on_disk",
143 "Sort by Size on Disk",
144 N_("by S_ize on Disk"),
145 N_("Keep icons sorted by disk usage in rows")
146 },
147 {
148 CAJA_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 CAJA_FILE_SORT_BY_MTIME,
156 "modification date",
157 "Sort by Modification Date",
158 N_("by Modification _Date"),
159 N_("Keep icons sorted by modification date in rows")
160 },
161 {
162 CAJA_FILE_SORT_BY_BTIME,
163 "creation date",
164 "Sort by Creation Date",
165 N_("by _Creation Date"),
166 N_("Keep icons sorted by creation date in rows")
167 },
168 {
169 CAJA_FILE_SORT_BY_EMBLEMS,
170 "emblems",
171 "Sort by Emblems",
172 N_("by _Emblems"),
173 N_("Keep icons sorted by emblems in rows")
174 },
175 {
176 CAJA_FILE_SORT_BY_TRASHED_TIME,
177 "trashed",
178 "Sort by Trash Time",
179 N_("by T_rash Time"),
180 N_("Keep icons sorted by trash time in rows")
181 },
182 {
183 CAJA_FILE_SORT_BY_EXTENSION,
184 "extension",
185 "Sort by Extension",
186 N_("by E_xtension"),
187 N_("Keep icons sorted by reversed extension segments in rows")
188 }
189 };
190
191 static gboolean default_sort_in_reverse_order = FALSE;
192 static int preview_sound_auto_value;
193
194 static void fm_icon_view_set_directory_sort_by (FMIconView *icon_view,
195 CajaFile *file,
196 const char *sort_by);
197 static void fm_icon_view_set_zoom_level (FMIconView *view,
198 CajaZoomLevel new_level,
199 gboolean always_emit);
200 static void fm_icon_view_update_click_mode (FMIconView *icon_view);
201 static void fm_icon_view_set_directory_tighter_layout (FMIconView *icon_view,
202 CajaFile *file,
203 gboolean tighter_layout);
204 static gboolean fm_icon_view_supports_manual_layout (FMIconView *icon_view);
205 static gboolean fm_icon_view_supports_scaling (FMIconView *icon_view);
206 static void fm_icon_view_reveal_selection (FMDirectoryView *view);
207 static const SortCriterion *get_sort_criterion_by_sort_type (CajaFileSortType sort_type);
208 static void set_sort_criterion_by_sort_type (FMIconView *icon_view,
209 CajaFileSortType sort_type);
210 static gboolean set_sort_reversed (FMIconView *icon_view,
211 gboolean new_value);
212 static void switch_to_manual_layout (FMIconView *view);
213 static void preview_audio (FMIconView *icon_view,
214 CajaFile *file,
215 gboolean start_flag);
216 static void update_layout_menus (FMIconView *view);
217 static CajaFileSortType get_default_sort_order (CajaFile *file,
218 gboolean *reversed);
219
220 static void default_sort_order_changed_callback (gpointer callback_data);
221 static void default_sort_in_reverse_order_changed_callback (gpointer callback_data);
222 static void default_use_tighter_layout_changed_callback (gpointer callback_data);
223 static void default_zoom_level_changed_callback (gpointer callback_data);
224 static void labels_beside_icons_changed_callback (gpointer callback_data);
225 static void all_columns_same_width_changed_callback (gpointer callback_data);
226
227 static void fm_icon_view_iface_init (CajaViewIface *iface);
228
229 G_DEFINE_TYPE_WITH_CODE (FMIconView, fm_icon_view, FM_TYPE_DIRECTORY_VIEW,
230 G_IMPLEMENT_INTERFACE (CAJA_TYPE_VIEW,
231 fm_icon_view_iface_init));
232
233 static void
fm_icon_view_destroy(GtkWidget * object)234 fm_icon_view_destroy (GtkWidget *object)
235 {
236 FMIconView *icon_view;
237
238 icon_view = FM_ICON_VIEW (object);
239
240 if (icon_view->details->react_to_icon_change_idle_id != 0)
241 {
242 g_source_remove (icon_view->details->react_to_icon_change_idle_id);
243 icon_view->details->react_to_icon_change_idle_id = 0;
244 }
245
246 if (icon_view->details->clipboard_handler_id != 0)
247 {
248 g_signal_handler_disconnect (caja_clipboard_monitor_get (),
249 icon_view->details->clipboard_handler_id);
250 icon_view->details->clipboard_handler_id = 0;
251 }
252
253 /* kill any sound preview process that is ongoing */
254 preview_audio (icon_view, NULL, FALSE);
255
256 if (icon_view->details->icons_not_positioned)
257 {
258 caja_file_list_free (icon_view->details->icons_not_positioned);
259 icon_view->details->icons_not_positioned = NULL;
260 }
261
262 GTK_WIDGET_CLASS (fm_icon_view_parent_class)->destroy (object);
263 }
264
265 static void
fm_icon_view_finalize(GObject * object)266 fm_icon_view_finalize (GObject *object)
267 {
268 FMIconView *icon_view;
269
270 icon_view = FM_ICON_VIEW (object);
271
272 g_free (icon_view->details);
273
274 g_signal_handlers_disconnect_by_func (caja_preferences,
275 default_sort_order_changed_callback,
276 icon_view);
277 g_signal_handlers_disconnect_by_func (caja_preferences,
278 default_sort_in_reverse_order_changed_callback,
279 icon_view);
280 g_signal_handlers_disconnect_by_func (caja_icon_view_preferences,
281 default_use_tighter_layout_changed_callback,
282 icon_view);
283 g_signal_handlers_disconnect_by_func (caja_icon_view_preferences,
284 default_zoom_level_changed_callback,
285 icon_view);
286 g_signal_handlers_disconnect_by_func (caja_icon_view_preferences,
287 labels_beside_icons_changed_callback,
288 icon_view);
289 g_signal_handlers_disconnect_by_func (caja_compact_view_preferences,
290 default_zoom_level_changed_callback,
291 icon_view);
292 g_signal_handlers_disconnect_by_func (caja_compact_view_preferences,
293 all_columns_same_width_changed_callback,
294 icon_view);
295
296 G_OBJECT_CLASS (fm_icon_view_parent_class)->finalize (object);
297 }
298
299 static CajaIconContainer *
get_icon_container(FMIconView * icon_view)300 get_icon_container (FMIconView *icon_view)
301 {
302 return CAJA_ICON_CONTAINER (gtk_bin_get_child (GTK_BIN (icon_view)));
303 }
304
305 static gboolean
get_stored_icon_position_callback(CajaIconContainer * container,CajaFile * file,CajaIconPosition * position,FMIconView * icon_view)306 get_stored_icon_position_callback (CajaIconContainer *container,
307 CajaFile *file,
308 CajaIconPosition *position,
309 FMIconView *icon_view)
310 {
311 char *position_string;
312 gboolean position_good;
313 char c;
314
315 g_assert (CAJA_IS_ICON_CONTAINER (container));
316 g_assert (CAJA_IS_FILE (file));
317 g_assert (position != NULL);
318 g_assert (FM_IS_ICON_VIEW (icon_view));
319
320 if (!fm_icon_view_supports_manual_layout (icon_view))
321 {
322 return FALSE;
323 }
324
325 /* Get the current position of this icon from the metadata. */
326 position_string = caja_file_get_metadata
327 (file, CAJA_METADATA_KEY_ICON_POSITION, "");
328 position_good = sscanf
329 (position_string, " %d , %d %c",
330 &position->x, &position->y, &c) == 2;
331 g_free (position_string);
332
333 /* If it is the desktop directory, maybe the mate-libs metadata has information about it */
334
335 /* Disable scaling if not on the desktop */
336 if (fm_icon_view_supports_scaling (icon_view))
337 {
338 char *scale_string;
339
340 /* Get the scale of the icon from the metadata. */
341 scale_string = caja_file_get_metadata
342 (file, CAJA_METADATA_KEY_ICON_SCALE, "1");
343 position->scale = g_ascii_strtod (scale_string, NULL);
344
345 if (errno != 0)
346 {
347 position->scale = 1.0;
348 }
349
350 g_free (scale_string);
351 }
352 else
353 {
354 position->scale = 1.0;
355 }
356
357 return position_good;
358 }
359
360 static void
real_set_sort_criterion(FMIconView * icon_view,const SortCriterion * sort,gboolean clear)361 real_set_sort_criterion (FMIconView *icon_view,
362 const SortCriterion *sort,
363 gboolean clear)
364 {
365 CajaFile *file;
366
367 file = fm_directory_view_get_directory_as_file (FM_DIRECTORY_VIEW (icon_view));
368
369 if (clear)
370 {
371 caja_file_set_metadata (file,
372 CAJA_METADATA_KEY_ICON_VIEW_SORT_BY, NULL, NULL);
373 caja_file_set_metadata (file,
374 CAJA_METADATA_KEY_ICON_VIEW_SORT_REVERSED, NULL, NULL);
375 icon_view->details->sort =
376 get_sort_criterion_by_sort_type (get_default_sort_order
377 (file, &icon_view->details->sort_reversed));
378 }
379 else
380 {
381 /* Store the new sort setting. */
382 fm_icon_view_set_directory_sort_by (icon_view,
383 file,
384 sort->metadata_text);
385 }
386
387 /* Update the layout menus to match the new sort setting. */
388 update_layout_menus (icon_view);
389 }
390
391 static void
set_sort_criterion(FMIconView * icon_view,const SortCriterion * sort)392 set_sort_criterion (FMIconView *icon_view, const SortCriterion *sort)
393 {
394 if (sort == NULL ||
395 icon_view->details->sort == sort)
396 {
397 return;
398 }
399
400 icon_view->details->sort = sort;
401
402 real_set_sort_criterion (icon_view, sort, FALSE);
403 }
404
405 static void
clear_sort_criterion(FMIconView * icon_view)406 clear_sort_criterion (FMIconView *icon_view)
407 {
408 real_set_sort_criterion (icon_view, NULL, TRUE);
409 }
410
411 static void
action_stretch_callback(GtkAction * action,gpointer callback_data)412 action_stretch_callback (GtkAction *action,
413 gpointer callback_data)
414 {
415 g_assert (FM_IS_ICON_VIEW (callback_data));
416
417 caja_icon_container_show_stretch_handles
418 (get_icon_container (FM_ICON_VIEW (callback_data)));
419 }
420
421 static void
action_unstretch_callback(GtkAction * action,gpointer callback_data)422 action_unstretch_callback (GtkAction *action,
423 gpointer callback_data)
424 {
425 g_assert (FM_IS_ICON_VIEW (callback_data));
426
427 caja_icon_container_unstretch
428 (get_icon_container (FM_ICON_VIEW (callback_data)));
429 }
430
431 static void
fm_icon_view_clean_up(FMIconView * icon_view)432 fm_icon_view_clean_up (FMIconView *icon_view)
433 {
434 EEL_CALL_METHOD (FM_ICON_VIEW_CLASS, icon_view, clean_up, (icon_view));
435 }
436
437 static void
fm_icon_view_real_clean_up(FMIconView * icon_view)438 fm_icon_view_real_clean_up (FMIconView *icon_view)
439 {
440 CajaIconContainer *icon_container;
441 gboolean saved_sort_reversed;
442
443 icon_container = get_icon_container (icon_view);
444
445 /* Hardwire Clean Up to always be by name, in forward order */
446 saved_sort_reversed = icon_view->details->sort_reversed;
447
448 set_sort_reversed (icon_view, FALSE);
449 set_sort_criterion (icon_view, &sort_criteria[0]);
450
451 caja_icon_container_sort (icon_container);
452 caja_icon_container_freeze_icon_positions (icon_container);
453
454 set_sort_reversed (icon_view, saved_sort_reversed);
455 }
456
457 static void
action_clean_up_callback(GtkAction * action,gpointer callback_data)458 action_clean_up_callback (GtkAction *action, gpointer callback_data)
459 {
460 fm_icon_view_clean_up (FM_ICON_VIEW (callback_data));
461 }
462
463 static void
set_tighter_layout(FMIconView * icon_view,gboolean new_value)464 set_tighter_layout (FMIconView *icon_view, gboolean new_value)
465 {
466 fm_icon_view_set_directory_tighter_layout (icon_view,
467 fm_directory_view_get_directory_as_file
468 (FM_DIRECTORY_VIEW (icon_view)),
469 new_value);
470 caja_icon_container_set_tighter_layout (get_icon_container (icon_view),
471 new_value);
472 }
473
474 static void
action_tighter_layout_callback(GtkAction * action,gpointer user_data)475 action_tighter_layout_callback (GtkAction *action,
476 gpointer user_data)
477 {
478 g_assert (FM_IS_ICON_VIEW (user_data));
479
480 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
481 set_tighter_layout (FM_ICON_VIEW (user_data),
482 gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
483 G_GNUC_END_IGNORE_DEPRECATIONS;
484 }
485
486
487 static gboolean
fm_icon_view_using_auto_layout(FMIconView * icon_view)488 fm_icon_view_using_auto_layout (FMIconView *icon_view)
489 {
490 return caja_icon_container_is_auto_layout
491 (get_icon_container (icon_view));
492 }
493
494 static gboolean
fm_icon_view_using_tighter_layout(FMIconView * icon_view)495 fm_icon_view_using_tighter_layout (FMIconView *icon_view)
496 {
497 return caja_icon_container_is_tighter_layout
498 (get_icon_container (icon_view));
499 }
500
501 static void
action_sort_radio_callback(GtkAction * action,GtkRadioAction * current,FMIconView * view)502 action_sort_radio_callback (GtkAction *action,
503 GtkRadioAction *current,
504 FMIconView *view)
505 {
506 CajaFileSortType sort_type;
507
508 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
509 sort_type = gtk_radio_action_get_current_value (current);
510 G_GNUC_END_IGNORE_DEPRECATIONS;
511
512 /* Note that id might be a toggle item.
513 * Ignore non-sort ids so that they don't cause sorting.
514 */
515 if (sort_type == CAJA_FILE_SORT_NONE)
516 {
517 switch_to_manual_layout (view);
518 }
519 else
520 {
521 set_sort_criterion_by_sort_type (view, sort_type);
522 }
523 }
524
525 static void
list_covers(CajaIconData * data,gpointer callback_data)526 list_covers (CajaIconData *data, gpointer callback_data)
527 {
528 GSList **file_list;
529
530 file_list = callback_data;
531
532 *file_list = g_slist_prepend (*file_list, data);
533 }
534
535 static void
unref_cover(CajaIconData * data,gpointer callback_data)536 unref_cover (CajaIconData *data, gpointer callback_data)
537 {
538 caja_file_unref (CAJA_FILE (data));
539 }
540
541 static void
fm_icon_view_clear(FMDirectoryView * view)542 fm_icon_view_clear (FMDirectoryView *view)
543 {
544 CajaIconContainer *icon_container;
545 GSList *file_list;
546
547 g_return_if_fail (FM_IS_ICON_VIEW (view));
548
549 icon_container = get_icon_container (FM_ICON_VIEW (view));
550 if (!icon_container)
551 return;
552
553 /* Clear away the existing icons. */
554 file_list = NULL;
555 caja_icon_container_for_each (icon_container, list_covers, &file_list);
556 caja_icon_container_clear (icon_container);
557 g_slist_foreach (file_list, (GFunc)unref_cover, NULL);
558 g_slist_free (file_list);
559 }
560
561
562 static gboolean
should_show_file_on_screen(FMDirectoryView * view,CajaFile * file)563 should_show_file_on_screen (FMDirectoryView *view, CajaFile *file)
564 {
565 if (!fm_directory_view_should_show_file (view, file))
566 {
567 return FALSE;
568 }
569
570 return TRUE;
571 }
572
573 static void
fm_icon_view_remove_file(FMDirectoryView * view,CajaFile * file,CajaDirectory * directory)574 fm_icon_view_remove_file (FMDirectoryView *view, CajaFile *file, CajaDirectory *directory)
575 {
576 FMIconView *icon_view;
577
578 /* This used to assert that 'directory == fm_directory_view_get_model (view)', but that
579 * resulted in a lot of crash reports (bug #352592). I don't see how that trace happens.
580 * It seems that somehow we get a files_changed event sent to the view from a directory
581 * that isn't the model, but the code disables the monitor and signal callback handlers when
582 * changing directories. Maybe we can get some more information when this happens.
583 * Further discussion in bug #368178.
584 */
585 if (directory != fm_directory_view_get_model (view))
586 {
587 char *file_uri, *dir_uri, *model_uri;
588 file_uri = caja_file_get_uri (file);
589 dir_uri = caja_directory_get_uri (directory);
590 model_uri = caja_directory_get_uri (fm_directory_view_get_model (view));
591 g_warning ("fm_icon_view_remove_file() - directory not icon view model, shouldn't happen.\n"
592 "file: %p:%s, dir: %p:%s, model: %p:%s, view loading: %d\n"
593 "If you see this, please add this info to https://bugzilla.gnome.org/show_bug.cgi?id=368178",
594 file, file_uri, directory, dir_uri, fm_directory_view_get_model (view), model_uri, fm_directory_view_get_loading (view));
595 g_free (file_uri);
596 g_free (dir_uri);
597 g_free (model_uri);
598 }
599
600 icon_view = FM_ICON_VIEW (view);
601
602 if (caja_icon_container_remove (get_icon_container (icon_view),
603 CAJA_ICON_CONTAINER_ICON_DATA (file)))
604 {
605 if (file == icon_view->details->audio_preview_file)
606 {
607 preview_audio (icon_view, NULL, FALSE);
608 }
609
610 caja_file_unref (file);
611 }
612 }
613
614 static void
fm_icon_view_add_file(FMDirectoryView * view,CajaFile * file,CajaDirectory * directory)615 fm_icon_view_add_file (FMDirectoryView *view, CajaFile *file, CajaDirectory *directory)
616 {
617 FMIconView *icon_view;
618 CajaIconContainer *icon_container;
619
620 g_assert (directory == fm_directory_view_get_model (view));
621
622 icon_view = FM_ICON_VIEW (view);
623 icon_container = get_icon_container (icon_view);
624
625 if (icon_view->details->filter_by_screen &&
626 !should_show_file_on_screen (view, file))
627 {
628 return;
629 }
630
631 /* Reset scroll region for the first icon added when loading a directory. */
632 if (fm_directory_view_get_loading (view) && caja_icon_container_is_empty (icon_container))
633 {
634 caja_icon_container_reset_scroll_region (icon_container);
635 }
636
637 if (caja_icon_container_add (icon_container,
638 CAJA_ICON_CONTAINER_ICON_DATA (file)))
639 {
640 caja_file_ref (file);
641 }
642 }
643
644 static void
fm_icon_view_flush_added_files(FMDirectoryView * view)645 fm_icon_view_flush_added_files (FMDirectoryView *view)
646 {
647 caja_icon_container_layout_now (get_icon_container (FM_ICON_VIEW (view)));
648 }
649
650 static void
fm_icon_view_file_changed(FMDirectoryView * view,CajaFile * file,CajaDirectory * directory)651 fm_icon_view_file_changed (FMDirectoryView *view, CajaFile *file, CajaDirectory *directory)
652 {
653 FMIconView *icon_view;
654
655 g_assert (directory == fm_directory_view_get_model (view));
656
657 g_return_if_fail (view != NULL);
658 icon_view = FM_ICON_VIEW (view);
659
660 if (!icon_view->details->filter_by_screen)
661 {
662 caja_icon_container_request_update
663 (get_icon_container (icon_view),
664 CAJA_ICON_CONTAINER_ICON_DATA (file));
665 return;
666 }
667
668 if (!should_show_file_on_screen (view, file))
669 {
670 fm_icon_view_remove_file (view, file, directory);
671 }
672 else
673 {
674
675 caja_icon_container_request_update
676 (get_icon_container (icon_view),
677 CAJA_ICON_CONTAINER_ICON_DATA (file));
678 }
679 }
680
681 static gboolean
fm_icon_view_supports_auto_layout(FMIconView * view)682 fm_icon_view_supports_auto_layout (FMIconView *view)
683 {
684 g_return_val_if_fail (FM_IS_ICON_VIEW (view), FALSE);
685
686 return EEL_CALL_METHOD_WITH_RETURN_VALUE
687 (FM_ICON_VIEW_CLASS, view,
688 supports_auto_layout, (view));
689 }
690
691 static gboolean
fm_icon_view_supports_scaling(FMIconView * view)692 fm_icon_view_supports_scaling (FMIconView *view)
693 {
694 g_return_val_if_fail (FM_IS_ICON_VIEW (view), FALSE);
695
696 return EEL_CALL_METHOD_WITH_RETURN_VALUE
697 (FM_ICON_VIEW_CLASS, view,
698 supports_scaling, (view));
699 }
700
701 static gboolean
fm_icon_view_supports_manual_layout(FMIconView * view)702 fm_icon_view_supports_manual_layout (FMIconView *view)
703 {
704 g_return_val_if_fail (FM_IS_ICON_VIEW (view), FALSE);
705
706 return EEL_CALL_METHOD_WITH_RETURN_VALUE
707 (FM_ICON_VIEW_CLASS, view,
708 supports_manual_layout, (view));
709 }
710
711 static gboolean
fm_icon_view_supports_keep_aligned(FMIconView * view)712 fm_icon_view_supports_keep_aligned (FMIconView *view)
713 {
714 g_return_val_if_fail (FM_IS_ICON_VIEW (view), FALSE);
715
716 return EEL_CALL_METHOD_WITH_RETURN_VALUE
717 (FM_ICON_VIEW_CLASS, view,
718 supports_keep_aligned, (view));
719 }
720
721 static gboolean
fm_icon_view_supports_labels_beside_icons(FMIconView * view)722 fm_icon_view_supports_labels_beside_icons (FMIconView *view)
723 {
724 g_return_val_if_fail (FM_IS_ICON_VIEW (view), FALSE);
725
726 return EEL_CALL_METHOD_WITH_RETURN_VALUE
727 (FM_ICON_VIEW_CLASS, view,
728 supports_labels_beside_icons, (view));
729 }
730
731 static gboolean
fm_icon_view_supports_tighter_layout(FMIconView * view)732 fm_icon_view_supports_tighter_layout (FMIconView *view)
733 {
734 return !fm_icon_view_is_compact (view);
735 }
736
737 static void
update_layout_menus(FMIconView * view)738 update_layout_menus (FMIconView *view)
739 {
740 gboolean is_auto_layout;
741 GtkAction *action;
742 CajaFile *file;
743
744 if (view->details->icon_action_group == NULL)
745 {
746 return;
747 }
748
749 is_auto_layout = fm_icon_view_using_auto_layout (view);
750 file = fm_directory_view_get_directory_as_file (FM_DIRECTORY_VIEW (view));
751
752 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
753 if (fm_icon_view_supports_auto_layout (view))
754 {
755 const char *action_name;
756
757 /* Mark sort criterion. */
758 action_name = is_auto_layout ? view->details->sort->action : FM_ACTION_MANUAL_LAYOUT;
759 action = gtk_action_group_get_action (view->details->icon_action_group,
760 action_name);
761 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
762
763 action = gtk_action_group_get_action (view->details->icon_action_group,
764 FM_ACTION_TIGHTER_LAYOUT);
765 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
766 fm_icon_view_using_tighter_layout (view));
767 gtk_action_set_sensitive (action, fm_icon_view_supports_tighter_layout (view));
768 gtk_action_set_visible (action, fm_icon_view_supports_tighter_layout (view));
769
770 action = gtk_action_group_get_action (view->details->icon_action_group,
771 FM_ACTION_REVERSED_ORDER);
772 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
773 view->details->sort_reversed);
774 gtk_action_set_sensitive (action, is_auto_layout);
775
776 action = gtk_action_group_get_action (view->details->icon_action_group,
777 FM_ACTION_SORT_TRASH_TIME);
778
779 if (file != NULL && caja_file_is_in_trash (file))
780 {
781 gtk_action_set_visible (action, TRUE);
782 }
783 else
784 {
785 gtk_action_set_visible (action, FALSE);
786 }
787 }
788
789 action = gtk_action_group_get_action (view->details->icon_action_group,
790 FM_ACTION_MANUAL_LAYOUT);
791 gtk_action_set_visible (action,
792 fm_icon_view_supports_manual_layout (view));
793
794 /* Clean Up is only relevant for manual layout */
795 action = gtk_action_group_get_action (view->details->icon_action_group,
796 FM_ACTION_CLEAN_UP);
797 gtk_action_set_sensitive (action, !is_auto_layout);
798
799 if (FM_IS_DESKTOP_ICON_VIEW (view))
800 {
801 gtk_action_set_label (action, _("_Organize Desktop by Name"));
802 }
803
804 action = gtk_action_group_get_action (view->details->icon_action_group,
805 FM_ACTION_KEEP_ALIGNED);
806 gtk_action_set_visible (action,
807 fm_icon_view_supports_keep_aligned (view));
808 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
809 caja_icon_container_is_keep_aligned (get_icon_container (view)));
810 gtk_action_set_sensitive (action, !is_auto_layout);
811
812 action = gtk_action_group_get_action (view->details->icon_action_group,
813 FM_ACTION_LOCK_ICON_POSITION);
814 gtk_action_set_visible (action, !is_auto_layout);
815 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
816 caja_icon_container_is_lock_icons_position (get_icon_container (view)));
817 G_GNUC_END_IGNORE_DEPRECATIONS;
818 }
819
820
821 static char *
fm_icon_view_get_directory_sort_by(FMIconView * icon_view,CajaFile * file)822 fm_icon_view_get_directory_sort_by (FMIconView *icon_view,
823 CajaFile *file)
824 {
825 if (!fm_icon_view_supports_auto_layout (icon_view))
826 {
827 return g_strdup ("name");
828 }
829
830 return EEL_CALL_METHOD_WITH_RETURN_VALUE
831 (FM_ICON_VIEW_CLASS, icon_view,
832 get_directory_sort_by, (icon_view, file));
833 }
834
835 static CajaFileSortType default_sort_order = CAJA_FILE_SORT_BY_DISPLAY_NAME;
836
837 static CajaFileSortType
get_default_sort_order(CajaFile * file,gboolean * reversed)838 get_default_sort_order (CajaFile *file, gboolean *reversed)
839 {
840 static gboolean auto_storaged_added = FALSE;
841 CajaFileSortType retval;
842
843 if (auto_storaged_added == FALSE)
844 {
845 auto_storaged_added = TRUE;
846 eel_g_settings_add_auto_enum (caja_preferences,
847 CAJA_PREFERENCES_DEFAULT_SORT_ORDER,
848 (int *) &default_sort_order);
849 eel_g_settings_add_auto_boolean (caja_preferences,
850 CAJA_PREFERENCES_DEFAULT_SORT_IN_REVERSE_ORDER,
851 &default_sort_in_reverse_order);
852 }
853
854 retval = caja_file_get_default_sort_type (file, reversed);
855
856 if (retval == CAJA_FILE_SORT_NONE)
857 {
858
859 if (reversed != NULL)
860 {
861 *reversed = default_sort_in_reverse_order;
862 }
863
864 retval = CLAMP (default_sort_order, CAJA_FILE_SORT_BY_DISPLAY_NAME,
865 CAJA_FILE_SORT_BY_EMBLEMS);
866 }
867
868 return retval;
869 }
870
871 static char *
fm_icon_view_real_get_directory_sort_by(FMIconView * icon_view,CajaFile * file)872 fm_icon_view_real_get_directory_sort_by (FMIconView *icon_view,
873 CajaFile *file)
874 {
875 const SortCriterion *default_sort_criterion;
876 default_sort_criterion = get_sort_criterion_by_sort_type (get_default_sort_order (file, NULL));
877 g_return_val_if_fail (default_sort_criterion != NULL, NULL);
878
879 return caja_file_get_metadata
880 (file, CAJA_METADATA_KEY_ICON_VIEW_SORT_BY,
881 default_sort_criterion->metadata_text);
882 }
883
884 static void
fm_icon_view_set_directory_sort_by(FMIconView * icon_view,CajaFile * file,const char * sort_by)885 fm_icon_view_set_directory_sort_by (FMIconView *icon_view,
886 CajaFile *file,
887 const char *sort_by)
888 {
889 if (!fm_icon_view_supports_auto_layout (icon_view))
890 {
891 return;
892 }
893
894 EEL_CALL_METHOD (FM_ICON_VIEW_CLASS, icon_view,
895 set_directory_sort_by, (icon_view, file, sort_by));
896 }
897
898 static void
fm_icon_view_real_set_directory_sort_by(FMIconView * icon_view,CajaFile * file,const char * sort_by)899 fm_icon_view_real_set_directory_sort_by (FMIconView *icon_view,
900 CajaFile *file,
901 const char *sort_by)
902 {
903 const SortCriterion *default_sort_criterion;
904 default_sort_criterion = get_sort_criterion_by_sort_type (get_default_sort_order (file, NULL));
905 g_return_if_fail (default_sort_criterion != NULL);
906
907 caja_file_set_metadata
908 (file, CAJA_METADATA_KEY_ICON_VIEW_SORT_BY,
909 default_sort_criterion->metadata_text,
910 sort_by);
911 }
912
913 static gboolean
fm_icon_view_get_directory_sort_reversed(FMIconView * icon_view,CajaFile * file)914 fm_icon_view_get_directory_sort_reversed (FMIconView *icon_view,
915 CajaFile *file)
916 {
917 if (!fm_icon_view_supports_auto_layout (icon_view))
918 {
919 return FALSE;
920 }
921
922 return EEL_CALL_METHOD_WITH_RETURN_VALUE
923 (FM_ICON_VIEW_CLASS, icon_view,
924 get_directory_sort_reversed, (icon_view, file));
925 }
926
927 static gboolean
fm_icon_view_real_get_directory_sort_reversed(FMIconView * icon_view,CajaFile * file)928 fm_icon_view_real_get_directory_sort_reversed (FMIconView *icon_view,
929 CajaFile *file)
930 {
931 gboolean reversed;
932
933 get_default_sort_order (file, &reversed);
934 return caja_file_get_boolean_metadata
935 (file,
936 CAJA_METADATA_KEY_ICON_VIEW_SORT_REVERSED,
937 reversed);
938 }
939
940 static void
fm_icon_view_set_directory_sort_reversed(FMIconView * icon_view,CajaFile * file,gboolean sort_reversed)941 fm_icon_view_set_directory_sort_reversed (FMIconView *icon_view,
942 CajaFile *file,
943 gboolean sort_reversed)
944 {
945 if (!fm_icon_view_supports_auto_layout (icon_view))
946 {
947 return;
948 }
949
950 EEL_CALL_METHOD (FM_ICON_VIEW_CLASS, icon_view,
951 set_directory_sort_reversed,
952 (icon_view, file, sort_reversed));
953 }
954
955 static void
fm_icon_view_real_set_directory_sort_reversed(FMIconView * icon_view,CajaFile * file,gboolean sort_reversed)956 fm_icon_view_real_set_directory_sort_reversed (FMIconView *icon_view,
957 CajaFile *file,
958 gboolean sort_reversed)
959 {
960 gboolean reversed;
961
962 get_default_sort_order (file, &reversed);
963 caja_file_set_boolean_metadata
964 (file,
965 CAJA_METADATA_KEY_ICON_VIEW_SORT_REVERSED,
966 reversed, sort_reversed);
967 }
968
969 static gboolean
get_default_directory_keep_aligned(void)970 get_default_directory_keep_aligned (void)
971 {
972 return TRUE;
973 }
974
975 static gboolean
fm_icon_view_get_directory_keep_aligned(FMIconView * icon_view,CajaFile * file)976 fm_icon_view_get_directory_keep_aligned (FMIconView *icon_view,
977 CajaFile *file)
978 {
979 if (!fm_icon_view_supports_keep_aligned (icon_view))
980 {
981 return FALSE;
982 }
983
984 return caja_file_get_boolean_metadata
985 (file,
986 CAJA_METADATA_KEY_ICON_VIEW_KEEP_ALIGNED,
987 get_default_directory_keep_aligned ());
988 }
989
990 static void
fm_icon_view_set_directory_keep_aligned(FMIconView * icon_view,CajaFile * file,gboolean keep_aligned)991 fm_icon_view_set_directory_keep_aligned (FMIconView *icon_view,
992 CajaFile *file,
993 gboolean keep_aligned)
994 {
995 if (!fm_icon_view_supports_keep_aligned (icon_view))
996 {
997 return;
998 }
999
1000 caja_file_set_boolean_metadata
1001 (file, CAJA_METADATA_KEY_ICON_VIEW_KEEP_ALIGNED,
1002 get_default_directory_keep_aligned (),
1003 keep_aligned);
1004 }
1005
1006 static gboolean
get_default_directory_lock_icons_position(void)1007 get_default_directory_lock_icons_position (void)
1008 {
1009 return FALSE;
1010 }
1011
1012 static gboolean
fm_icon_view_get_directory_lock_icons_position(FMIconView * icon_view,CajaFile * file)1013 fm_icon_view_get_directory_lock_icons_position (FMIconView *icon_view,
1014 CajaFile *file)
1015 {
1016 if (!fm_icon_view_supports_manual_layout (icon_view))
1017 {
1018 return FALSE;
1019 }
1020
1021 return caja_file_get_boolean_metadata
1022 (file,
1023 CAJA_METADATA_KEY_ICON_VIEW_LOCK_ICONS_POSITION,
1024 get_default_directory_lock_icons_position ());
1025 }
1026
1027 static void
fm_icon_view_set_directory_lock_icons_position(FMIconView * icon_view,CajaFile * file,gboolean lock_icons_position)1028 fm_icon_view_set_directory_lock_icons_position (FMIconView *icon_view,
1029 CajaFile *file,
1030 gboolean lock_icons_position)
1031 {
1032 if (!fm_icon_view_supports_manual_layout (icon_view))
1033 {
1034 return;
1035 }
1036
1037 caja_file_set_boolean_metadata
1038 (file, CAJA_METADATA_KEY_ICON_VIEW_LOCK_ICONS_POSITION,
1039 get_default_directory_lock_icons_position (),
1040 lock_icons_position);
1041 }
1042
1043 static gboolean
fm_icon_view_get_directory_auto_layout(FMIconView * icon_view,CajaFile * file)1044 fm_icon_view_get_directory_auto_layout (FMIconView *icon_view,
1045 CajaFile *file)
1046 {
1047 if (!fm_icon_view_supports_auto_layout (icon_view))
1048 {
1049 return FALSE;
1050 }
1051
1052 if (!fm_icon_view_supports_manual_layout (icon_view))
1053 {
1054 return TRUE;
1055 }
1056
1057 return EEL_CALL_METHOD_WITH_RETURN_VALUE
1058 (FM_ICON_VIEW_CLASS, icon_view,
1059 get_directory_auto_layout, (icon_view, file));
1060 }
1061
1062 static gboolean
fm_icon_view_real_get_directory_auto_layout(FMIconView * icon_view,CajaFile * file)1063 fm_icon_view_real_get_directory_auto_layout (FMIconView *icon_view,
1064 CajaFile *file)
1065 {
1066
1067
1068 return caja_file_get_boolean_metadata
1069 (file, CAJA_METADATA_KEY_ICON_VIEW_AUTO_LAYOUT, TRUE);
1070 }
1071
1072 static void
fm_icon_view_set_directory_auto_layout(FMIconView * icon_view,CajaFile * file,gboolean auto_layout)1073 fm_icon_view_set_directory_auto_layout (FMIconView *icon_view,
1074 CajaFile *file,
1075 gboolean auto_layout)
1076 {
1077 if (!fm_icon_view_supports_auto_layout (icon_view) ||
1078 !fm_icon_view_supports_manual_layout (icon_view))
1079 {
1080 return;
1081 }
1082
1083 EEL_CALL_METHOD (FM_ICON_VIEW_CLASS, icon_view,
1084 set_directory_auto_layout, (icon_view, file, auto_layout));
1085 }
1086
1087 static void
fm_icon_view_real_set_directory_auto_layout(FMIconView * icon_view,CajaFile * file,gboolean auto_layout)1088 fm_icon_view_real_set_directory_auto_layout (FMIconView *icon_view,
1089 CajaFile *file,
1090 gboolean auto_layout)
1091 {
1092 if (!fm_icon_view_supports_manual_layout (icon_view))
1093 {
1094 return;
1095 }
1096
1097 caja_file_set_boolean_metadata
1098 (file, CAJA_METADATA_KEY_ICON_VIEW_AUTO_LAYOUT,
1099 TRUE,
1100 auto_layout);
1101 }
1102 /* maintainence of tighter layout boolean */
1103
1104 static gboolean
fm_icon_view_get_directory_tighter_layout(FMIconView * icon_view,CajaFile * file)1105 fm_icon_view_get_directory_tighter_layout (FMIconView *icon_view,
1106 CajaFile *file)
1107 {
1108 return EEL_CALL_METHOD_WITH_RETURN_VALUE
1109 (FM_ICON_VIEW_CLASS, icon_view,
1110 get_directory_tighter_layout, (icon_view, file));
1111 }
1112
1113 static gboolean default_directory_tighter_layout = FALSE;
1114
1115 static gboolean
get_default_directory_tighter_layout(void)1116 get_default_directory_tighter_layout (void)
1117 {
1118 static gboolean auto_storaged_added = FALSE;
1119
1120 if (auto_storaged_added == FALSE)
1121 {
1122 auto_storaged_added = TRUE;
1123 eel_g_settings_add_auto_boolean (caja_icon_view_preferences,
1124 CAJA_PREFERENCES_ICON_VIEW_DEFAULT_USE_TIGHTER_LAYOUT,
1125 &default_directory_tighter_layout);
1126 }
1127
1128 return default_directory_tighter_layout;
1129 }
1130
1131 static gboolean
fm_icon_view_real_get_directory_tighter_layout(FMIconView * icon_view,CajaFile * file)1132 fm_icon_view_real_get_directory_tighter_layout (FMIconView *icon_view,
1133 CajaFile *file)
1134 {
1135 if (!fm_icon_view_supports_tighter_layout (icon_view))
1136 {
1137 return FALSE;
1138 }
1139
1140 return caja_file_get_boolean_metadata
1141 (file,
1142 CAJA_METADATA_KEY_ICON_VIEW_TIGHTER_LAYOUT,
1143 get_default_directory_tighter_layout ());
1144 }
1145
1146 static void
fm_icon_view_set_directory_tighter_layout(FMIconView * icon_view,CajaFile * file,gboolean tighter_layout)1147 fm_icon_view_set_directory_tighter_layout (FMIconView *icon_view,
1148 CajaFile *file,
1149 gboolean tighter_layout)
1150 {
1151 EEL_CALL_METHOD (FM_ICON_VIEW_CLASS, icon_view,
1152 set_directory_tighter_layout, (icon_view, file, tighter_layout));
1153 }
1154
1155 static void
fm_icon_view_real_set_directory_tighter_layout(FMIconView * icon_view,CajaFile * file,gboolean tighter_layout)1156 fm_icon_view_real_set_directory_tighter_layout (FMIconView *icon_view,
1157 CajaFile *file,
1158 gboolean tighter_layout)
1159 {
1160 if (!fm_icon_view_supports_tighter_layout (icon_view))
1161 {
1162 return;
1163 }
1164
1165 caja_file_set_boolean_metadata
1166 (file, CAJA_METADATA_KEY_ICON_VIEW_TIGHTER_LAYOUT,
1167 get_default_directory_tighter_layout (),
1168 tighter_layout);
1169 }
1170
1171 static gboolean
real_supports_auto_layout(FMIconView * view)1172 real_supports_auto_layout (FMIconView *view)
1173 {
1174 g_return_val_if_fail (FM_IS_ICON_VIEW (view), FALSE);
1175
1176 return TRUE;
1177 }
1178
1179 static gboolean
real_supports_scaling(FMIconView * view)1180 real_supports_scaling (FMIconView *view)
1181 {
1182 g_return_val_if_fail (FM_IS_ICON_VIEW (view), FALSE);
1183
1184 return FALSE;
1185 }
1186
1187 static gboolean
real_supports_manual_layout(FMIconView * view)1188 real_supports_manual_layout (FMIconView *view)
1189 {
1190 g_return_val_if_fail (FM_IS_ICON_VIEW (view), FALSE);
1191
1192 return !fm_icon_view_is_compact (view);
1193 }
1194
1195 static gboolean
real_supports_keep_aligned(FMIconView * view)1196 real_supports_keep_aligned (FMIconView *view)
1197 {
1198 g_return_val_if_fail (FM_IS_ICON_VIEW (view), FALSE);
1199
1200 return FALSE;
1201 }
1202
1203 static gboolean
real_supports_labels_beside_icons(FMIconView * view)1204 real_supports_labels_beside_icons (FMIconView *view)
1205 {
1206 g_return_val_if_fail (FM_IS_ICON_VIEW (view), TRUE);
1207
1208 return TRUE;
1209 }
1210
1211 static gboolean
set_sort_reversed(FMIconView * icon_view,gboolean new_value)1212 set_sort_reversed (FMIconView *icon_view, gboolean new_value)
1213 {
1214 if (icon_view->details->sort_reversed == new_value)
1215 {
1216 return FALSE;
1217 }
1218 icon_view->details->sort_reversed = new_value;
1219
1220 /* Store the new sort setting. */
1221 fm_icon_view_set_directory_sort_reversed (icon_view, fm_directory_view_get_directory_as_file (FM_DIRECTORY_VIEW (icon_view)), new_value);
1222
1223 /* Update the layout menus to match the new sort-order setting. */
1224 update_layout_menus (icon_view);
1225
1226 return TRUE;
1227 }
1228
1229 static const SortCriterion *
get_sort_criterion_by_metadata_text(const char * metadata_text)1230 get_sort_criterion_by_metadata_text (const char *metadata_text)
1231 {
1232 guint i;
1233
1234 /* Figure out what the new sort setting should be. */
1235 for (i = 0; i < G_N_ELEMENTS (sort_criteria); i++)
1236 {
1237 if (g_strcmp0 (sort_criteria[i].metadata_text, metadata_text) == 0)
1238 {
1239 return &sort_criteria[i];
1240 }
1241 }
1242 return NULL;
1243 }
1244
1245 static const SortCriterion *
get_sort_criterion_by_sort_type(CajaFileSortType sort_type)1246 get_sort_criterion_by_sort_type (CajaFileSortType sort_type)
1247 {
1248 guint i;
1249
1250 /* Figure out what the new sort setting should be. */
1251 for (i = 0; i < G_N_ELEMENTS (sort_criteria); i++)
1252 {
1253 if (sort_type == sort_criteria[i].sort_type)
1254 {
1255 return &sort_criteria[i];
1256 }
1257 }
1258
1259 return NULL;
1260 }
1261
1262 static CajaZoomLevel default_zoom_level = CAJA_ZOOM_LEVEL_STANDARD;
1263 static CajaZoomLevel default_compact_zoom_level = CAJA_ZOOM_LEVEL_STANDARD;
1264 #define DEFAULT_ZOOM_LEVEL(icon_view) icon_view->details->compact ? default_compact_zoom_level : default_zoom_level
1265
1266 static CajaZoomLevel
get_default_zoom_level(FMIconView * icon_view)1267 get_default_zoom_level (FMIconView *icon_view)
1268 {
1269 static gboolean auto_storage_added = FALSE;
1270
1271 if (!auto_storage_added)
1272 {
1273 auto_storage_added = TRUE;
1274 eel_g_settings_add_auto_enum (caja_icon_view_preferences,
1275 CAJA_PREFERENCES_ICON_VIEW_DEFAULT_ZOOM_LEVEL,
1276 (int *) &default_zoom_level);
1277 eel_g_settings_add_auto_enum (caja_compact_view_preferences,
1278 CAJA_PREFERENCES_COMPACT_VIEW_DEFAULT_ZOOM_LEVEL,
1279 (int *) &default_compact_zoom_level);
1280 }
1281
1282 return MIN (DEFAULT_ZOOM_LEVEL(icon_view), CAJA_ZOOM_LEVEL_LARGEST);
1283 }
1284
1285 static void
set_labels_beside_icons(FMIconView * icon_view)1286 set_labels_beside_icons (FMIconView *icon_view)
1287 {
1288 gboolean labels_beside;
1289
1290 if (fm_icon_view_supports_labels_beside_icons (icon_view))
1291 {
1292 labels_beside = fm_icon_view_is_compact (icon_view) ||
1293 g_settings_get_boolean (caja_icon_view_preferences, CAJA_PREFERENCES_ICON_VIEW_LABELS_BESIDE_ICONS);
1294
1295 if (labels_beside)
1296 {
1297 caja_icon_container_set_label_position
1298 (get_icon_container (icon_view),
1299 CAJA_ICON_LABEL_POSITION_BESIDE);
1300 }
1301 else
1302 {
1303 caja_icon_container_set_label_position
1304 (get_icon_container (icon_view),
1305 CAJA_ICON_LABEL_POSITION_UNDER);
1306 }
1307 }
1308 }
1309
1310 static void
set_columns_same_width(FMIconView * icon_view)1311 set_columns_same_width (FMIconView *icon_view)
1312 {
1313 gboolean all_columns_same_width;
1314
1315 if (fm_icon_view_is_compact (icon_view))
1316 {
1317 all_columns_same_width = g_settings_get_boolean (caja_compact_view_preferences, CAJA_PREFERENCES_COMPACT_VIEW_ALL_COLUMNS_SAME_WIDTH);
1318 caja_icon_container_set_all_columns_same_width (get_icon_container (icon_view), all_columns_same_width);
1319 }
1320 }
1321
1322 static void
fm_icon_view_begin_loading(FMDirectoryView * view)1323 fm_icon_view_begin_loading (FMDirectoryView *view)
1324 {
1325 FMIconView *icon_view;
1326 GtkWidget *icon_container;
1327 CajaFile *file;
1328 char *sort_name;
1329
1330 g_return_if_fail (FM_IS_ICON_VIEW (view));
1331
1332 icon_view = FM_ICON_VIEW (view);
1333 file = fm_directory_view_get_directory_as_file (view);
1334 icon_container = GTK_WIDGET (get_icon_container (icon_view));
1335
1336 caja_icon_container_begin_loading (CAJA_ICON_CONTAINER (icon_container));
1337
1338 caja_icon_container_set_allow_moves (CAJA_ICON_CONTAINER (icon_container),
1339 fm_directory_view_get_allow_moves (view));
1340
1341 /* kill any sound preview process that is ongoing */
1342 preview_audio (icon_view, NULL, FALSE);
1343 /* FIXME bugzilla.gnome.org 45060: Should use methods instead
1344 * of hardcoding desktop knowledge in here.
1345 */
1346 if (FM_IS_DESKTOP_ICON_VIEW (view))
1347 {
1348 caja_connect_desktop_background_to_settings (CAJA_ICON_CONTAINER (icon_container));
1349 }
1350 else
1351 {
1352 GdkDragAction default_action;
1353
1354 if (caja_window_info_get_window_type (fm_directory_view_get_caja_window (view)) == CAJA_WINDOW_NAVIGATION)
1355 {
1356 default_action = CAJA_DND_ACTION_SET_AS_GLOBAL_BACKGROUND;
1357 }
1358 else
1359 {
1360 default_action = CAJA_DND_ACTION_SET_AS_FOLDER_BACKGROUND;
1361 }
1362
1363 caja_connect_background_to_file_metadata (icon_container, file, default_action);
1364 }
1365
1366 /* Set up the zoom level from the metadata. */
1367 if (fm_directory_view_supports_zooming (FM_DIRECTORY_VIEW (icon_view)))
1368 {
1369 int level;
1370
1371 if (icon_view->details->compact)
1372 {
1373 level = caja_file_get_integer_metadata
1374 (file,
1375 CAJA_METADATA_KEY_COMPACT_VIEW_ZOOM_LEVEL,
1376 get_default_zoom_level (icon_view));
1377 }
1378 else
1379 {
1380 level = caja_file_get_integer_metadata
1381 (file,
1382 CAJA_METADATA_KEY_ICON_VIEW_ZOOM_LEVEL,
1383 get_default_zoom_level (icon_view));
1384 }
1385
1386 fm_icon_view_set_zoom_level (icon_view, level, TRUE);
1387 }
1388
1389 /* Set the sort mode.
1390 * It's OK not to resort the icons because the
1391 * container doesn't have any icons at this point.
1392 */
1393 sort_name = fm_icon_view_get_directory_sort_by (icon_view, file);
1394 set_sort_criterion (icon_view, get_sort_criterion_by_metadata_text (sort_name));
1395 g_free (sort_name);
1396
1397 /* Set the sort direction from the metadata. */
1398 set_sort_reversed (icon_view, fm_icon_view_get_directory_sort_reversed (icon_view, file));
1399
1400 caja_icon_container_set_keep_aligned
1401 (get_icon_container (icon_view),
1402 fm_icon_view_get_directory_keep_aligned (icon_view, file));
1403 caja_icon_container_set_lock_icons_position
1404 (get_icon_container (icon_view),
1405 fm_icon_view_get_directory_lock_icons_position (icon_view, file));
1406 caja_icon_container_set_tighter_layout
1407 (get_icon_container (icon_view),
1408 fm_icon_view_get_directory_tighter_layout (icon_view, file));
1409
1410 set_labels_beside_icons (icon_view);
1411 set_columns_same_width (icon_view);
1412
1413 /* We must set auto-layout last, because it invokes the layout_changed
1414 * callback, which works incorrectly if the other layout criteria are
1415 * not already set up properly (see bug 6500, e.g.)
1416 */
1417 caja_icon_container_set_auto_layout
1418 (get_icon_container (icon_view),
1419 fm_icon_view_get_directory_auto_layout (icon_view, file));
1420
1421 /* e.g. keep aligned may have changed */
1422 update_layout_menus (icon_view);
1423 }
1424
1425 static void
icon_view_notify_clipboard_info(CajaClipboardMonitor * monitor,CajaClipboardInfo * info,FMIconView * icon_view)1426 icon_view_notify_clipboard_info (CajaClipboardMonitor *monitor,
1427 CajaClipboardInfo *info,
1428 FMIconView *icon_view)
1429 {
1430 GList *icon_data;
1431
1432 icon_data = NULL;
1433 if (info && info->cut)
1434 {
1435 icon_data = info->files;
1436 }
1437
1438 caja_icon_container_set_highlighted_for_clipboard (
1439 get_icon_container (icon_view), icon_data);
1440 }
1441
1442 static void
fm_icon_view_end_loading(FMDirectoryView * view,gboolean all_files_seen)1443 fm_icon_view_end_loading (FMDirectoryView *view,
1444 gboolean all_files_seen)
1445 {
1446 FMIconView *icon_view;
1447 GtkWidget *icon_container;
1448 CajaClipboardMonitor *monitor;
1449 CajaClipboardInfo *info;
1450
1451 icon_view = FM_ICON_VIEW (view);
1452
1453 icon_container = GTK_WIDGET (get_icon_container (icon_view));
1454 caja_icon_container_end_loading (CAJA_ICON_CONTAINER (icon_container), all_files_seen);
1455
1456 monitor = caja_clipboard_monitor_get ();
1457 info = caja_clipboard_monitor_get_clipboard_info (monitor);
1458
1459 icon_view_notify_clipboard_info (monitor, info, icon_view);
1460 }
1461
1462 static CajaZoomLevel
fm_icon_view_get_zoom_level(FMDirectoryView * view)1463 fm_icon_view_get_zoom_level (FMDirectoryView *view)
1464 {
1465 g_return_val_if_fail (FM_IS_ICON_VIEW (view), CAJA_ZOOM_LEVEL_STANDARD);
1466
1467 return caja_icon_container_get_zoom_level (get_icon_container (FM_ICON_VIEW (view)));
1468 }
1469
1470 static void
fm_icon_view_set_zoom_level(FMIconView * view,CajaZoomLevel new_level,gboolean always_emit)1471 fm_icon_view_set_zoom_level (FMIconView *view,
1472 CajaZoomLevel new_level,
1473 gboolean always_emit)
1474 {
1475 CajaIconContainer *icon_container;
1476
1477 g_return_if_fail (FM_IS_ICON_VIEW (view));
1478 g_return_if_fail (new_level >= CAJA_ZOOM_LEVEL_SMALLEST &&
1479 new_level <= CAJA_ZOOM_LEVEL_LARGEST);
1480
1481 icon_container = get_icon_container (view);
1482 if (caja_icon_container_get_zoom_level (icon_container) == new_level)
1483 {
1484 if (always_emit)
1485 {
1486 g_signal_emit_by_name (view, "zoom_level_changed");
1487 }
1488 return;
1489 }
1490
1491 if (view->details->compact)
1492 {
1493 caja_file_set_integer_metadata
1494 (fm_directory_view_get_directory_as_file (FM_DIRECTORY_VIEW (view)),
1495 CAJA_METADATA_KEY_COMPACT_VIEW_ZOOM_LEVEL,
1496 get_default_zoom_level (view),
1497 new_level);
1498 }
1499 else
1500 {
1501 caja_file_set_integer_metadata
1502 (fm_directory_view_get_directory_as_file (FM_DIRECTORY_VIEW (view)),
1503 CAJA_METADATA_KEY_ICON_VIEW_ZOOM_LEVEL,
1504 get_default_zoom_level (view),
1505 new_level);
1506 }
1507
1508 caja_icon_container_set_zoom_level (icon_container, new_level);
1509
1510 g_signal_emit_by_name (view, "zoom_level_changed");
1511
1512 if (fm_directory_view_get_active (FM_DIRECTORY_VIEW (view)))
1513 {
1514 fm_directory_view_update_menus (FM_DIRECTORY_VIEW (view));
1515 }
1516 }
1517
1518 static void
fm_icon_view_bump_zoom_level(FMDirectoryView * view,int zoom_increment)1519 fm_icon_view_bump_zoom_level (FMDirectoryView *view, int zoom_increment)
1520 {
1521 CajaZoomLevel new_level;
1522
1523 g_return_if_fail (FM_IS_ICON_VIEW (view));
1524
1525 new_level = fm_icon_view_get_zoom_level (view) + zoom_increment;
1526
1527 if (new_level >= CAJA_ZOOM_LEVEL_SMALLEST &&
1528 new_level <= CAJA_ZOOM_LEVEL_LARGEST)
1529 {
1530 fm_directory_view_zoom_to_level (view, new_level);
1531 }
1532 }
1533
1534 static void
fm_icon_view_zoom_to_level(FMDirectoryView * view,CajaZoomLevel zoom_level)1535 fm_icon_view_zoom_to_level (FMDirectoryView *view,
1536 CajaZoomLevel zoom_level)
1537 {
1538 FMIconView *icon_view;
1539
1540 g_assert (FM_IS_ICON_VIEW (view));
1541
1542 icon_view = FM_ICON_VIEW (view);
1543 fm_icon_view_set_zoom_level (icon_view, zoom_level, FALSE);
1544 }
1545
1546 static void
fm_icon_view_restore_default_zoom_level(FMDirectoryView * view)1547 fm_icon_view_restore_default_zoom_level (FMDirectoryView *view)
1548 {
1549 FMIconView *icon_view;
1550
1551 g_return_if_fail (FM_IS_ICON_VIEW (view));
1552
1553 icon_view = FM_ICON_VIEW (view);
1554 fm_directory_view_zoom_to_level
1555 (view, get_default_zoom_level (icon_view));
1556 }
1557
1558 static gboolean
fm_icon_view_can_zoom_in(FMDirectoryView * view)1559 fm_icon_view_can_zoom_in (FMDirectoryView *view)
1560 {
1561 g_return_val_if_fail (FM_IS_ICON_VIEW (view), FALSE);
1562
1563 return fm_icon_view_get_zoom_level (view)
1564 < CAJA_ZOOM_LEVEL_LARGEST;
1565 }
1566
1567 static gboolean
fm_icon_view_can_zoom_out(FMDirectoryView * view)1568 fm_icon_view_can_zoom_out (FMDirectoryView *view)
1569 {
1570 g_return_val_if_fail (FM_IS_ICON_VIEW (view), FALSE);
1571
1572 return fm_icon_view_get_zoom_level (view)
1573 > CAJA_ZOOM_LEVEL_SMALLEST;
1574 }
1575
1576 static GtkWidget *
fm_icon_view_get_background_widget(FMDirectoryView * view)1577 fm_icon_view_get_background_widget (FMDirectoryView *view)
1578 {
1579 g_return_val_if_fail (FM_IS_ICON_VIEW (view), NULL);
1580
1581 return GTK_WIDGET (get_icon_container (FM_ICON_VIEW (view)));
1582 }
1583
1584 static gboolean
fm_icon_view_is_empty(FMDirectoryView * view)1585 fm_icon_view_is_empty (FMDirectoryView *view)
1586 {
1587 g_assert (FM_IS_ICON_VIEW (view));
1588
1589 return caja_icon_container_is_empty
1590 (get_icon_container (FM_ICON_VIEW (view)));
1591 }
1592
1593 static GList *
fm_icon_view_get_selection(FMDirectoryView * view)1594 fm_icon_view_get_selection (FMDirectoryView *view)
1595 {
1596 GList *list;
1597
1598 g_return_val_if_fail (FM_IS_ICON_VIEW (view), NULL);
1599
1600 list = caja_icon_container_get_selection
1601 (get_icon_container (FM_ICON_VIEW (view)));
1602 caja_file_list_ref (list);
1603 return list;
1604 }
1605
1606 static void
count_item(CajaIconData * icon_data,gpointer callback_data)1607 count_item (CajaIconData *icon_data,
1608 gpointer callback_data)
1609 {
1610 guint *count;
1611
1612 count = callback_data;
1613 (*count)++;
1614 }
1615
1616 static guint
fm_icon_view_get_item_count(FMDirectoryView * view)1617 fm_icon_view_get_item_count (FMDirectoryView *view)
1618 {
1619 guint count;
1620
1621 g_return_val_if_fail (FM_IS_ICON_VIEW (view), 0);
1622
1623 count = 0;
1624
1625 caja_icon_container_for_each
1626 (get_icon_container (FM_ICON_VIEW (view)),
1627 count_item, &count);
1628
1629 return count;
1630 }
1631
1632 static void
set_sort_criterion_by_sort_type(FMIconView * icon_view,CajaFileSortType sort_type)1633 set_sort_criterion_by_sort_type (FMIconView *icon_view,
1634 CajaFileSortType sort_type)
1635 {
1636 const SortCriterion *sort;
1637
1638 g_assert (FM_IS_ICON_VIEW (icon_view));
1639
1640 sort = get_sort_criterion_by_sort_type (sort_type);
1641 g_return_if_fail (sort != NULL);
1642
1643 if (sort == icon_view->details->sort
1644 && fm_icon_view_using_auto_layout (icon_view))
1645 {
1646 return;
1647 }
1648
1649 set_sort_criterion (icon_view, sort);
1650 caja_icon_container_sort (get_icon_container (icon_view));
1651 fm_icon_view_reveal_selection (FM_DIRECTORY_VIEW (icon_view));
1652 }
1653
1654
1655 static void
action_reversed_order_callback(GtkAction * action,gpointer user_data)1656 action_reversed_order_callback (GtkAction *action,
1657 gpointer user_data)
1658 {
1659 FMIconView *icon_view;
1660
1661 icon_view = FM_ICON_VIEW (user_data);
1662
1663 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
1664 if (set_sort_reversed (icon_view,
1665 gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))))
1666 {
1667 caja_icon_container_sort (get_icon_container (icon_view));
1668 fm_icon_view_reveal_selection (FM_DIRECTORY_VIEW (icon_view));
1669 }
1670 G_GNUC_END_IGNORE_DEPRECATIONS;
1671 }
1672
1673 static void
action_keep_aligned_callback(GtkAction * action,gpointer user_data)1674 action_keep_aligned_callback (GtkAction *action,
1675 gpointer user_data)
1676 {
1677 FMIconView *icon_view;
1678 CajaFile *file;
1679 gboolean keep_aligned;
1680
1681 icon_view = FM_ICON_VIEW (user_data);
1682
1683 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
1684 keep_aligned = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1685 G_GNUC_END_IGNORE_DEPRECATIONS;
1686
1687 file = fm_directory_view_get_directory_as_file (FM_DIRECTORY_VIEW (icon_view));
1688 fm_icon_view_set_directory_keep_aligned (icon_view,
1689 file,
1690 keep_aligned);
1691
1692 caja_icon_container_set_keep_aligned (get_icon_container (icon_view),
1693 keep_aligned);
1694 }
1695
1696 static void
action_lock_icons_position_callback(GtkAction * action,gpointer user_data)1697 action_lock_icons_position_callback (GtkAction *action,
1698 gpointer user_data)
1699 {
1700 FMIconView *icon_view;
1701 CajaFile *file;
1702 gboolean lock_icons_position;
1703
1704 icon_view = FM_ICON_VIEW (user_data);
1705
1706 lock_icons_position = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1707
1708 file = fm_directory_view_get_directory_as_file (FM_DIRECTORY_VIEW (icon_view));
1709 fm_icon_view_set_directory_lock_icons_position (icon_view,
1710 file,
1711 lock_icons_position);
1712
1713 caja_icon_container_set_lock_icons_position (get_icon_container (icon_view),
1714 lock_icons_position);
1715 }
1716
1717 static void
switch_to_manual_layout(FMIconView * icon_view)1718 switch_to_manual_layout (FMIconView *icon_view)
1719 {
1720 if (!fm_icon_view_using_auto_layout (icon_view))
1721 {
1722 return;
1723 }
1724
1725 icon_view->details->sort = &sort_criteria[0];
1726
1727 caja_icon_container_set_auto_layout
1728 (get_icon_container (icon_view), FALSE);
1729 }
1730
1731 static void
layout_changed_callback(CajaIconContainer * container,FMIconView * icon_view)1732 layout_changed_callback (CajaIconContainer *container,
1733 FMIconView *icon_view)
1734 {
1735 CajaFile *file;
1736
1737 g_assert (FM_IS_ICON_VIEW (icon_view));
1738 g_assert (container == get_icon_container (icon_view));
1739
1740 file = fm_directory_view_get_directory_as_file (FM_DIRECTORY_VIEW (icon_view));
1741
1742 if (file != NULL)
1743 {
1744 fm_icon_view_set_directory_auto_layout
1745 (icon_view,
1746 file,
1747 fm_icon_view_using_auto_layout (icon_view));
1748 fm_icon_view_set_directory_tighter_layout
1749 (icon_view,
1750 file,
1751 fm_icon_view_using_tighter_layout (icon_view));
1752 }
1753
1754 update_layout_menus (icon_view);
1755 }
1756
1757 static gboolean
fm_icon_view_can_rename_file(FMDirectoryView * view,CajaFile * file)1758 fm_icon_view_can_rename_file (FMDirectoryView *view, CajaFile *file)
1759 {
1760 if (!(fm_icon_view_get_zoom_level (view) > CAJA_ZOOM_LEVEL_SMALLEST))
1761 {
1762 return FALSE;
1763 }
1764
1765 return FM_DIRECTORY_VIEW_CLASS(fm_icon_view_parent_class)->can_rename_file (view, file);
1766 }
1767
1768 static void
fm_icon_view_start_renaming_file(FMDirectoryView * view,CajaFile * file,gboolean select_all)1769 fm_icon_view_start_renaming_file (FMDirectoryView *view,
1770 CajaFile *file,
1771 gboolean select_all)
1772 {
1773 /* call parent class to make sure the right icon is selected */
1774 FM_DIRECTORY_VIEW_CLASS(fm_icon_view_parent_class)->start_renaming_file (view, file, select_all);
1775
1776 /* start renaming */
1777 caja_icon_container_start_renaming_selected_item
1778 (get_icon_container (FM_ICON_VIEW (view)), select_all);
1779 }
1780
1781 static const GtkActionEntry icon_view_entries[] =
1782 {
1783 /* name, stock id, label */ { "Arrange Items", NULL, N_("Arran_ge Items"),
1784 NULL, NULL, NULL },
1785 /* name, stock id */ { "Stretch", NULL,
1786 /* label, accelerator */ N_("Resize Icon..."), NULL,
1787 /* tooltip */ N_("Make the selected icon resizable"),
1788 G_CALLBACK (action_stretch_callback) },
1789 /* name, stock id */ { "Unstretch", NULL,
1790 /* label, accelerator */ N_("Restore Icons' Original Si_zes"), NULL,
1791 /* tooltip */ N_("Restore each selected icon to its original size"),
1792 G_CALLBACK (action_unstretch_callback) },
1793 /* name, stock id */ { "Clean Up", NULL,
1794 /* label, accelerator */ N_("_Organize by Name"), NULL,
1795 /* tooltip */ N_("Reposition icons to better fit in the window and avoid overlapping"),
1796 G_CALLBACK (action_clean_up_callback) },
1797 };
1798
1799 static const GtkToggleActionEntry icon_view_toggle_entries[] =
1800 {
1801 /* name, stock id */ { "Tighter Layout", NULL,
1802 /* label, accelerator */ N_("Compact _Layout"), NULL,
1803 /* tooltip */ N_("Toggle using a tighter layout scheme"),
1804 G_CALLBACK (action_tighter_layout_callback),
1805 0
1806 },
1807 /* name, stock id */ { "Reversed Order", NULL,
1808 /* label, accelerator */ N_("Re_versed Order"), NULL,
1809 /* tooltip */ N_("Display icons in the opposite order"),
1810 G_CALLBACK (action_reversed_order_callback),
1811 0
1812 },
1813 /* name, stock id */ { "Keep Aligned", NULL,
1814 /* label, accelerator */ N_("_Keep Aligned"), NULL,
1815 /* tooltip */ N_("Keep icons lined up on a grid"),
1816 G_CALLBACK (action_keep_aligned_callback),
1817 0
1818 },
1819 /* name, stock id */ { "Lock Icons Position", NULL,
1820 /* label, accelerator */ N_("_Lock Icons Position"), NULL,
1821 /* tooltip */ N_("Prevent repositioning icons"),
1822 G_CALLBACK (action_lock_icons_position_callback),
1823 0
1824 },
1825 };
1826
1827 static const GtkRadioActionEntry arrange_radio_entries[] =
1828 {
1829 {
1830 "Manual Layout", NULL,
1831 N_("_Manually"), NULL,
1832 N_("Leave icons wherever they are dropped"),
1833 CAJA_FILE_SORT_NONE
1834 },
1835 {
1836 "Sort by Name", NULL,
1837 N_("By _Name"), NULL,
1838 N_("Keep icons sorted by name in rows"),
1839 CAJA_FILE_SORT_BY_DISPLAY_NAME
1840 },
1841 {
1842 "Sort by Size", NULL,
1843 N_("By _Size"), NULL,
1844 N_("Keep icons sorted by size in rows"),
1845 CAJA_FILE_SORT_BY_SIZE
1846 },
1847 {
1848 "Sort by Size on Disk", NULL,
1849 N_("By S_ize on Disk"), NULL,
1850 N_("Keep icons sorted by disk usage in rows"),
1851 CAJA_FILE_SORT_BY_SIZE_ON_DISK
1852 },
1853 {
1854 "Sort by Type", NULL,
1855 N_("By _Type"), NULL,
1856 N_("Keep icons sorted by type in rows"),
1857 CAJA_FILE_SORT_BY_TYPE
1858 },
1859 {
1860 "Sort by Modification Date", NULL,
1861 N_("By Modification _Date"), NULL,
1862 N_("Keep icons sorted by modification date in rows"),
1863 CAJA_FILE_SORT_BY_MTIME
1864 },
1865 {
1866 "Sort by Creation Date", NULL,
1867 N_("By _Creation Date"), NULL,
1868 N_("Keep icons sorted by creation date in rows"),
1869 CAJA_FILE_SORT_BY_BTIME
1870 },
1871 {
1872 "Sort by Emblems", NULL,
1873 N_("By _Emblems"), NULL,
1874 N_("Keep icons sorted by emblems in rows"),
1875 CAJA_FILE_SORT_BY_EMBLEMS
1876 },
1877 {
1878 "Sort by Trash Time", NULL,
1879 N_("By T_rash Time"), NULL,
1880 N_("Keep icons sorted by trash time in rows"),
1881 CAJA_FILE_SORT_BY_TRASHED_TIME
1882 },
1883 {
1884 "Sort by Extension", NULL,
1885 N_("By E_xtension"), NULL,
1886 N_("Keep icons sorted by reverse extension segments in rows"),
1887 CAJA_FILE_SORT_BY_EXTENSION
1888 },
1889 };
1890
1891 static void
fm_icon_view_merge_menus(FMDirectoryView * view)1892 fm_icon_view_merge_menus (FMDirectoryView *view)
1893 {
1894 FMIconView *icon_view;
1895 GtkUIManager *ui_manager;
1896 GtkActionGroup *action_group;
1897 const char *ui;
1898
1899 g_assert (FM_IS_ICON_VIEW (view));
1900
1901 FM_DIRECTORY_VIEW_CLASS (fm_icon_view_parent_class)->merge_menus (view);
1902
1903 icon_view = FM_ICON_VIEW (view);
1904
1905 ui_manager = fm_directory_view_get_ui_manager (FM_DIRECTORY_VIEW (icon_view));
1906
1907 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
1908 action_group = gtk_action_group_new ("IconViewActions");
1909 #ifdef ENABLE_NLS
1910 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1911 #endif /* ENABLE_NLS */
1912 icon_view->details->icon_action_group = action_group;
1913 gtk_action_group_add_actions (action_group,
1914 icon_view_entries, G_N_ELEMENTS (icon_view_entries),
1915 icon_view);
1916 gtk_action_group_add_toggle_actions (action_group,
1917 icon_view_toggle_entries, G_N_ELEMENTS (icon_view_toggle_entries),
1918 icon_view);
1919 gtk_action_group_add_radio_actions (action_group,
1920 arrange_radio_entries,
1921 G_N_ELEMENTS (arrange_radio_entries),
1922 -1,
1923 G_CALLBACK (action_sort_radio_callback),
1924 icon_view);
1925 G_GNUC_END_IGNORE_DEPRECATIONS;
1926
1927 gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
1928 g_object_unref (action_group); /* owned by ui manager */
1929
1930 ui = caja_ui_string_get ("caja-icon-view-ui.xml");
1931 icon_view->details->icon_merge_id =
1932 gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, NULL);
1933
1934 /* Do one-time state-setting here; context-dependent state-setting
1935 * is done in update_menus.
1936 */
1937 if (!fm_icon_view_supports_auto_layout (icon_view))
1938 {
1939 GtkAction *action;
1940
1941 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
1942 action = gtk_action_group_get_action (action_group,
1943 FM_ACTION_ARRANGE_ITEMS);
1944 gtk_action_set_visible (action, FALSE);
1945 G_GNUC_END_IGNORE_DEPRECATIONS;
1946 }
1947
1948 if (fm_icon_view_supports_scaling (icon_view))
1949 {
1950 gtk_ui_manager_add_ui (ui_manager,
1951 icon_view->details->icon_merge_id,
1952 POPUP_PATH_ICON_APPEARANCE,
1953 FM_ACTION_STRETCH,
1954 FM_ACTION_STRETCH,
1955 GTK_UI_MANAGER_MENUITEM,
1956 FALSE);
1957 gtk_ui_manager_add_ui (ui_manager,
1958 icon_view->details->icon_merge_id,
1959 POPUP_PATH_ICON_APPEARANCE,
1960 FM_ACTION_UNSTRETCH,
1961 FM_ACTION_UNSTRETCH,
1962 GTK_UI_MANAGER_MENUITEM,
1963 FALSE);
1964 }
1965
1966 update_layout_menus (icon_view);
1967 }
1968
1969 static void
fm_icon_view_unmerge_menus(FMDirectoryView * view)1970 fm_icon_view_unmerge_menus (FMDirectoryView *view)
1971 {
1972 FMIconView *icon_view;
1973 GtkUIManager *ui_manager;
1974
1975 icon_view = FM_ICON_VIEW (view);
1976
1977 FM_DIRECTORY_VIEW_CLASS (fm_icon_view_parent_class)->unmerge_menus (view);
1978
1979 ui_manager = fm_directory_view_get_ui_manager (view);
1980 if (ui_manager != NULL)
1981 {
1982 caja_ui_unmerge_ui (ui_manager,
1983 &icon_view->details->icon_merge_id,
1984 &icon_view->details->icon_action_group);
1985 }
1986 }
1987
1988 static void
fm_icon_view_update_menus(FMDirectoryView * view)1989 fm_icon_view_update_menus (FMDirectoryView *view)
1990 {
1991 FMIconView *icon_view;
1992 GList *selection;
1993 int selection_count;
1994 GtkAction *action;
1995 CajaIconContainer *icon_container;
1996 gboolean editable;
1997
1998 icon_view = FM_ICON_VIEW (view);
1999
2000 FM_DIRECTORY_VIEW_CLASS (fm_icon_view_parent_class)->update_menus(view);
2001
2002 selection = fm_directory_view_get_selection (view);
2003 selection_count = g_list_length (selection);
2004 icon_container = get_icon_container (icon_view);
2005
2006 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
2007 action = gtk_action_group_get_action (icon_view->details->icon_action_group,
2008 FM_ACTION_STRETCH);
2009 gtk_action_set_sensitive (action,
2010 selection_count == 1
2011 && icon_container != NULL
2012 && !caja_icon_container_has_stretch_handles (icon_container));
2013
2014 gtk_action_set_visible (action,
2015 fm_icon_view_supports_scaling (icon_view));
2016
2017 action = gtk_action_group_get_action (icon_view->details->icon_action_group,
2018 FM_ACTION_UNSTRETCH);
2019 g_object_set (action, "label",
2020 eel_g_list_more_than_one_item (selection)
2021 ? _("Restore Icons' Original Si_zes")
2022 : _("Restore Icon's Original Si_ze"),
2023 NULL);
2024 gtk_action_set_sensitive (action,
2025 icon_container != NULL
2026 && caja_icon_container_is_stretched (icon_container));
2027
2028 gtk_action_set_visible (action,
2029 fm_icon_view_supports_scaling (icon_view));
2030
2031 caja_file_list_free (selection);
2032
2033 editable = fm_directory_view_is_editable (view);
2034 action = gtk_action_group_get_action (icon_view->details->icon_action_group,
2035 FM_ACTION_MANUAL_LAYOUT);
2036 gtk_action_set_sensitive (action, editable);
2037 G_GNUC_END_IGNORE_DEPRECATIONS;
2038 }
2039
2040 static void
fm_icon_view_reset_to_defaults(FMDirectoryView * view)2041 fm_icon_view_reset_to_defaults (FMDirectoryView *view)
2042 {
2043 CajaIconContainer *icon_container;
2044 FMIconView *icon_view;
2045
2046 icon_view = FM_ICON_VIEW (view);
2047 icon_container = get_icon_container (icon_view);
2048
2049 clear_sort_criterion (icon_view);
2050 caja_icon_container_set_keep_aligned
2051 (icon_container, get_default_directory_keep_aligned ());
2052 caja_icon_container_set_lock_icons_position
2053 (icon_container, get_default_directory_lock_icons_position ());
2054 caja_icon_container_set_tighter_layout
2055 (icon_container, get_default_directory_tighter_layout ());
2056
2057 caja_icon_container_sort (icon_container);
2058
2059 update_layout_menus (icon_view);
2060
2061 fm_icon_view_restore_default_zoom_level (view);
2062 }
2063
2064 static void
fm_icon_view_select_all(FMDirectoryView * view)2065 fm_icon_view_select_all (FMDirectoryView *view)
2066 {
2067 CajaIconContainer *icon_container;
2068
2069 g_return_if_fail (FM_IS_ICON_VIEW (view));
2070
2071 icon_container = get_icon_container (FM_ICON_VIEW (view));
2072 caja_icon_container_select_all (icon_container);
2073 }
2074
2075 static void
fm_icon_view_reveal_selection(FMDirectoryView * view)2076 fm_icon_view_reveal_selection (FMDirectoryView *view)
2077 {
2078 GList *selection;
2079
2080 g_return_if_fail (FM_IS_ICON_VIEW (view));
2081
2082 selection = fm_directory_view_get_selection (view);
2083
2084 /* Make sure at least one of the selected items is scrolled into view */
2085 if (selection != NULL)
2086 {
2087 caja_icon_container_reveal
2088 (get_icon_container (FM_ICON_VIEW (view)),
2089 selection->data);
2090 }
2091
2092 caja_file_list_free (selection);
2093 }
2094
2095 static GArray *
fm_icon_view_get_selected_icon_locations(FMDirectoryView * view)2096 fm_icon_view_get_selected_icon_locations (FMDirectoryView *view)
2097 {
2098 g_return_val_if_fail (FM_IS_ICON_VIEW (view), NULL);
2099
2100 return caja_icon_container_get_selected_icon_locations
2101 (get_icon_container (FM_ICON_VIEW (view)));
2102 }
2103
2104
2105 static void
fm_icon_view_set_selection(FMDirectoryView * view,GList * selection)2106 fm_icon_view_set_selection (FMDirectoryView *view, GList *selection)
2107 {
2108 g_return_if_fail (FM_IS_ICON_VIEW (view));
2109
2110 caja_icon_container_set_selection
2111 (get_icon_container (FM_ICON_VIEW (view)), selection);
2112 }
2113
2114 static void
fm_icon_view_invert_selection(FMDirectoryView * view)2115 fm_icon_view_invert_selection (FMDirectoryView *view)
2116 {
2117 g_return_if_fail (FM_IS_ICON_VIEW (view));
2118
2119 caja_icon_container_invert_selection
2120 (get_icon_container (FM_ICON_VIEW (view)));
2121 }
2122
2123 static gboolean
fm_icon_view_using_manual_layout(FMDirectoryView * view)2124 fm_icon_view_using_manual_layout (FMDirectoryView *view)
2125 {
2126 g_return_val_if_fail (FM_IS_ICON_VIEW (view), FALSE);
2127
2128 return !fm_icon_view_using_auto_layout (FM_ICON_VIEW (view));
2129 }
2130
2131 static void
fm_icon_view_widget_to_file_operation_position(FMDirectoryView * view,GdkPoint * position)2132 fm_icon_view_widget_to_file_operation_position (FMDirectoryView *view,
2133 GdkPoint *position)
2134 {
2135 g_assert (FM_IS_ICON_VIEW (view));
2136
2137 caja_icon_container_widget_to_file_operation_position
2138 (get_icon_container (FM_ICON_VIEW (view)), position);
2139 }
2140
2141 static void
icon_container_activate_callback(CajaIconContainer * container,GList * file_list,FMIconView * icon_view)2142 icon_container_activate_callback (CajaIconContainer *container,
2143 GList *file_list,
2144 FMIconView *icon_view)
2145 {
2146 g_assert (FM_IS_ICON_VIEW (icon_view));
2147 g_assert (container == get_icon_container (icon_view));
2148
2149 fm_directory_view_activate_files (FM_DIRECTORY_VIEW (icon_view),
2150 file_list,
2151 CAJA_WINDOW_OPEN_ACCORDING_TO_MODE, 0,
2152 TRUE);
2153 }
2154
2155 static void
icon_container_activate_alternate_callback(CajaIconContainer * container,GList * file_list,FMIconView * icon_view)2156 icon_container_activate_alternate_callback (CajaIconContainer *container,
2157 GList *file_list,
2158 FMIconView *icon_view)
2159 {
2160 gboolean open_in_tab;
2161 CajaWindowInfo *window_info;
2162 CajaWindowOpenFlags flags;
2163
2164 g_assert (FM_IS_ICON_VIEW (icon_view));
2165 g_assert (container == get_icon_container (icon_view));
2166
2167 open_in_tab = TRUE;
2168
2169 window_info = fm_directory_view_get_caja_window (FM_DIRECTORY_VIEW (icon_view));
2170
2171 if (caja_window_info_get_window_type (window_info) == CAJA_WINDOW_NAVIGATION)
2172 {
2173 GdkEvent *event;
2174
2175 event = gtk_get_current_event ();
2176
2177 if (event->type == GDK_BUTTON_PRESS ||
2178 event->type == GDK_BUTTON_RELEASE ||
2179 event->type == GDK_2BUTTON_PRESS ||
2180 event->type == GDK_3BUTTON_PRESS)
2181 {
2182 GdkEventButton *button_event;
2183
2184 button_event = (GdkEventButton *) event;
2185 open_in_tab = (button_event->state & GDK_SHIFT_MASK) == 0;
2186 }
2187 else if (event->type == GDK_KEY_PRESS ||
2188 event->type == GDK_KEY_RELEASE)
2189 {
2190 GdkEventKey *key_event;
2191
2192 key_event = (GdkEventKey *) event;
2193 open_in_tab = !((key_event->state & GDK_SHIFT_MASK) != 0 &&
2194 (key_event->state & GDK_CONTROL_MASK) != 0);
2195 }
2196 else
2197 {
2198 open_in_tab = TRUE;
2199 }
2200 }
2201
2202 flags = CAJA_WINDOW_OPEN_FLAG_CLOSE_BEHIND;
2203 if (open_in_tab)
2204 {
2205 flags |= CAJA_WINDOW_OPEN_FLAG_NEW_TAB;
2206 }
2207 else
2208 {
2209 flags |= CAJA_WINDOW_OPEN_FLAG_NEW_WINDOW;
2210 }
2211
2212 fm_directory_view_activate_files (FM_DIRECTORY_VIEW (icon_view),
2213 file_list,
2214 CAJA_WINDOW_OPEN_ACCORDING_TO_MODE,
2215 flags,
2216 TRUE);
2217 }
2218
2219 static void
band_select_started_callback(CajaIconContainer * container,FMIconView * icon_view)2220 band_select_started_callback (CajaIconContainer *container,
2221 FMIconView *icon_view)
2222 {
2223 g_assert (FM_IS_ICON_VIEW (icon_view));
2224 g_assert (container == get_icon_container (icon_view));
2225
2226 fm_directory_view_start_batching_selection_changes (FM_DIRECTORY_VIEW (icon_view));
2227 }
2228
2229 static void
band_select_ended_callback(CajaIconContainer * container,FMIconView * icon_view)2230 band_select_ended_callback (CajaIconContainer *container,
2231 FMIconView *icon_view)
2232 {
2233 g_assert (FM_IS_ICON_VIEW (icon_view));
2234 g_assert (container == get_icon_container (icon_view));
2235
2236 fm_directory_view_stop_batching_selection_changes (FM_DIRECTORY_VIEW (icon_view));
2237 }
2238
2239 /* handle the preview signal by inspecting the mime type. For now, we only preview local sound files. */
2240
2241 static char **
get_preview_argv(char * uri)2242 get_preview_argv (char *uri)
2243 {
2244 char *command;
2245
2246 command = g_find_program_in_path ("gst-launch-1.0");
2247
2248 if (!command)
2249 {
2250 command = g_find_program_in_path ("gst-launch-0.10");
2251 }
2252
2253 if (command)
2254 {
2255 char **argv;
2256 int i;
2257
2258 argv = g_new (char *, 5);
2259 i = 0;
2260 argv[i++] = command;
2261 argv[i++] = g_strdup ("playbin");
2262 argv[i++] = g_strconcat ("uri=", uri, NULL);
2263 /* do not display videos */
2264 argv[i++] = g_strdup ("video-sink=fakesink");
2265 argv[i++] = NULL;
2266 return argv;
2267 }
2268
2269 return NULL;
2270 }
2271
2272 static void
audio_child_died(GPid pid,gint status,gpointer data)2273 audio_child_died (GPid pid,
2274 gint status,
2275 gpointer data)
2276 {
2277 FMIconView *icon_view;
2278
2279 g_return_if_fail (FM_IS_ICON_VIEW (data));
2280
2281 icon_view = FM_ICON_VIEW (data);
2282
2283 icon_view->details->audio_preview_child_watch = 0;
2284 icon_view->details->audio_preview_child_pid = 0;
2285 }
2286
2287 /* here's the timer task that actually plays the file using mpg123, ogg123 or play. */
2288 /* FIXME bugzilla.gnome.org 41258: we should get the application from our mime-type stuff */
2289 static gboolean
play_file(gpointer callback_data)2290 play_file (gpointer callback_data)
2291 {
2292 CajaFile *file;
2293 FMIconView *icon_view;
2294 GPid child_pid;
2295 char **argv;
2296 GError *error;
2297 char *uri;
2298 GFile *gfile;
2299 char *path;
2300
2301 icon_view = FM_ICON_VIEW (callback_data);
2302
2303 /* Stop timeout */
2304 icon_view->details->audio_preview_timeout = 0;
2305
2306 file = icon_view->details->audio_preview_file;
2307 gfile = caja_file_get_location (file);
2308 path = g_file_get_path (gfile);
2309
2310 /* if we have a local path, use that instead of the native URI.
2311 * this can be useful for special GVfs mounts, such as cdda://
2312 */
2313 if (path) {
2314 uri = g_filename_to_uri (path, NULL, NULL);
2315 } else {
2316 uri = caja_file_get_uri (file);
2317 }
2318
2319 g_object_unref (gfile);
2320 g_free (path);
2321
2322 argv = get_preview_argv (uri);
2323 g_free (uri);
2324 if (argv == NULL)
2325 {
2326 return FALSE;
2327 }
2328
2329 error = NULL;
2330 if (!g_spawn_async_with_pipes (NULL,
2331 argv,
2332 NULL,
2333 G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL,
2334 NULL,
2335 NULL /* user_data */,
2336 &child_pid,
2337 NULL, NULL, NULL,
2338 &error))
2339 {
2340 g_strfreev (argv);
2341 g_warning ("Error spawning sound preview: %s\n", error->message);
2342 g_error_free (error);
2343 return FALSE;
2344 }
2345 g_strfreev (argv);
2346
2347 icon_view->details->audio_preview_child_watch =
2348 g_child_watch_add (child_pid,
2349 audio_child_died, NULL);
2350 icon_view->details->audio_preview_child_pid = child_pid;
2351
2352 return FALSE;
2353 }
2354
2355 /* FIXME bugzilla.gnome.org 42530: Hardcoding this here sucks. We should be using components
2356 * for open ended things like this.
2357 */
2358
2359 /* this routine is invoked from the preview signal handler to preview a sound file. We
2360 want to wait a suitable delay until we actually do it, so set up a timer task to actually
2361 start playing. If we move out before the task files, we remove it. */
2362
2363 static void
preview_audio(FMIconView * icon_view,CajaFile * file,gboolean start_flag)2364 preview_audio (FMIconView *icon_view, CajaFile *file, gboolean start_flag)
2365 {
2366 /* Stop current audio playback */
2367 if (icon_view->details->audio_preview_child_pid != 0)
2368 {
2369 kill (icon_view->details->audio_preview_child_pid, SIGTERM);
2370 g_source_remove (icon_view->details->audio_preview_child_watch);
2371 waitpid (icon_view->details->audio_preview_child_pid, NULL, 0);
2372 icon_view->details->audio_preview_child_pid = 0;
2373 }
2374
2375 if (icon_view->details->audio_preview_timeout != 0)
2376 {
2377 g_source_remove (icon_view->details->audio_preview_timeout);
2378 icon_view->details->audio_preview_timeout = 0;
2379 }
2380
2381 if (start_flag)
2382 {
2383 icon_view->details->audio_preview_file = file;
2384 icon_view->details->audio_preview_timeout = g_timeout_add_seconds (1, play_file, icon_view);
2385 }
2386 }
2387
2388 static gboolean
sound_preview_type_supported(CajaFile * file)2389 sound_preview_type_supported (CajaFile *file)
2390 {
2391 char *mime_type;
2392 guint i;
2393
2394 mime_type = caja_file_get_mime_type (file);
2395 if (mime_type == NULL)
2396 {
2397 return FALSE;
2398 }
2399 for (i = 0; i < G_N_ELEMENTS (audio_mime_types); i++)
2400 {
2401 if (g_content_type_is_a (mime_type, audio_mime_types[i]))
2402 {
2403 g_free (mime_type);
2404 return TRUE;
2405 }
2406 }
2407
2408 g_free (mime_type);
2409 return FALSE;
2410 }
2411
2412
2413 static gboolean
should_preview_sound(CajaFile * file)2414 should_preview_sound (CajaFile *file)
2415 {
2416 GFile *location;
2417 GFilesystemPreviewType use_preview;
2418
2419 use_preview = caja_file_get_filesystem_use_preview (file);
2420
2421 location = caja_file_get_location (file);
2422 if (g_file_has_uri_scheme (location, "burn"))
2423 {
2424 g_object_unref (location);
2425 return FALSE;
2426 }
2427 g_object_unref (location);
2428
2429 /* Check user performance preference */
2430 if (preview_sound_auto_value == CAJA_SPEED_TRADEOFF_NEVER)
2431 {
2432 return FALSE;
2433 }
2434
2435 if (preview_sound_auto_value == CAJA_SPEED_TRADEOFF_ALWAYS)
2436 {
2437 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER)
2438 {
2439 return FALSE;
2440 }
2441 else
2442 {
2443 return TRUE;
2444 }
2445 }
2446
2447 if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_NEVER)
2448 {
2449 /* file system says to never preview anything */
2450 return FALSE;
2451 }
2452 else if (use_preview == G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL)
2453 {
2454 /* file system says we should treat file as if it's local */
2455 return TRUE;
2456 }
2457 else
2458 {
2459 /* only local files */
2460 return caja_file_is_local (file);
2461 }
2462 }
2463
2464 static int
icon_container_preview_callback(CajaIconContainer * container,CajaFile * file,gboolean start_flag,FMIconView * icon_view)2465 icon_container_preview_callback (CajaIconContainer *container,
2466 CajaFile *file,
2467 gboolean start_flag,
2468 FMIconView *icon_view)
2469 {
2470 int result;
2471
2472 result = 0;
2473
2474 /* preview files based on the mime_type. */
2475 /* at first, we just handle sounds */
2476 if (should_preview_sound (file))
2477 {
2478 if (sound_preview_type_supported (file))
2479 {
2480 result = 1;
2481 preview_audio (icon_view, file, start_flag);
2482 }
2483 }
2484
2485 /* Display file name in status area at low zoom levels, since
2486 * the name is not displayed or hard to read in the icon view.
2487 */
2488 if (fm_icon_view_get_zoom_level (FM_DIRECTORY_VIEW (icon_view)) <= CAJA_ZOOM_LEVEL_SMALLER)
2489 {
2490 if (start_flag)
2491 {
2492 char *file_name, *message;
2493
2494 file_name = caja_file_get_display_name (file);
2495 message = g_strdup_printf (_("pointing at \"%s\""), file_name);
2496 g_free (file_name);
2497 caja_window_slot_info_set_status
2498 (fm_directory_view_get_caja_window_slot (FM_DIRECTORY_VIEW (icon_view)),
2499 message);
2500 g_free (message);
2501 }
2502 else
2503 {
2504 fm_directory_view_display_selection_info (FM_DIRECTORY_VIEW(icon_view));
2505 }
2506 }
2507
2508 return result;
2509 }
2510
2511 static void
renaming_icon_callback(CajaIconContainer * container,GtkWidget * widget,gpointer callback_data)2512 renaming_icon_callback (CajaIconContainer *container,
2513 GtkWidget *widget,
2514 gpointer callback_data)
2515 {
2516 FMDirectoryView *directory_view;
2517
2518 directory_view = FM_DIRECTORY_VIEW (callback_data);
2519 caja_clipboard_set_up_editable
2520 (GTK_EDITABLE (widget),
2521 fm_directory_view_get_ui_manager (directory_view),
2522 FALSE);
2523 }
2524
2525 int
fm_icon_view_compare_files(FMIconView * icon_view,CajaFile * a,CajaFile * b)2526 fm_icon_view_compare_files (FMIconView *icon_view,
2527 CajaFile *a,
2528 CajaFile *b)
2529 {
2530 return caja_file_compare_for_sort
2531 (a, b, icon_view->details->sort->sort_type,
2532 /* Use type-unsafe cast for performance */
2533 fm_directory_view_should_sort_directories_first ((FMDirectoryView *)icon_view),
2534 icon_view->details->sort_reversed);
2535 }
2536
2537 static int
compare_files(FMDirectoryView * icon_view,CajaFile * a,CajaFile * b)2538 compare_files (FMDirectoryView *icon_view,
2539 CajaFile *a,
2540 CajaFile *b)
2541 {
2542 return fm_icon_view_compare_files ((FMIconView *)icon_view, a, b);
2543 }
2544
2545
2546 void
fm_icon_view_filter_by_screen(FMIconView * icon_view,gboolean filter)2547 fm_icon_view_filter_by_screen (FMIconView *icon_view,
2548 gboolean filter)
2549 {
2550 icon_view->details->filter_by_screen = filter;
2551 }
2552
2553 static void
fm_icon_view_screen_changed(GtkWidget * widget,GdkScreen * previous_screen)2554 fm_icon_view_screen_changed (GtkWidget *widget,
2555 GdkScreen *previous_screen)
2556 {
2557 FMDirectoryView *view;
2558 GList *files, *l;
2559
2560 if (GTK_WIDGET_CLASS (fm_icon_view_parent_class)->screen_changed)
2561 {
2562 GTK_WIDGET_CLASS (fm_icon_view_parent_class)->screen_changed (widget, previous_screen);
2563 }
2564
2565 view = FM_DIRECTORY_VIEW (widget);
2566 if (FM_ICON_VIEW (view)->details->filter_by_screen)
2567 {
2568 CajaDirectory *directory;
2569 CajaIconContainer *icon_container;
2570 CajaFile *file = NULL;
2571
2572 icon_container = get_icon_container (FM_ICON_VIEW (view));
2573
2574 directory = fm_directory_view_get_model (view);
2575 files = caja_directory_get_file_list (directory);
2576
2577 for (l = files; l != NULL; l = l->next)
2578 {
2579 file = l->data;
2580
2581 if (!should_show_file_on_screen (view, file))
2582 {
2583 fm_icon_view_remove_file (view, file, directory);
2584 }
2585 else
2586 {
2587 if (caja_icon_container_add (icon_container,
2588 CAJA_ICON_CONTAINER_ICON_DATA (file)))
2589 {
2590 caja_file_ref (file);
2591 }
2592 }
2593 }
2594
2595 caja_file_list_unref (files);
2596 g_list_free (files);
2597 }
2598 }
2599
2600 static gboolean
fm_icon_view_scroll_event(GtkWidget * widget,GdkEventScroll * scroll_event)2601 fm_icon_view_scroll_event (GtkWidget *widget,
2602 GdkEventScroll *scroll_event)
2603 {
2604 FMIconView *icon_view;
2605 gboolean ret;
2606
2607 icon_view = FM_ICON_VIEW (widget);
2608
2609 if(icon_view->details->compact)
2610 {
2611 if((ret = fm_directory_view_handle_scroll_event(FM_DIRECTORY_VIEW(icon_view), scroll_event)))
2612 return ret;
2613
2614 if(scroll_event->direction == GDK_SCROLL_UP)
2615 scroll_event->direction = GDK_SCROLL_LEFT;
2616 else if(scroll_event->direction == GDK_SCROLL_DOWN)
2617 scroll_event->direction = GDK_SCROLL_RIGHT;
2618 else if(scroll_event->direction == GDK_SCROLL_SMOOTH)
2619 {
2620 /* no x value implies only vertical scrolling enabled */
2621 if(scroll_event->delta_x == 0.0)
2622 {
2623 /* convert vertical to horizontal */
2624 scroll_event->delta_x = scroll_event->delta_y;
2625 scroll_event->delta_y = 0.0;
2626 }
2627 }
2628 }
2629
2630 return GTK_WIDGET_CLASS (fm_icon_view_parent_class)->scroll_event (widget, scroll_event);
2631 }
2632
2633 static void
selection_changed_callback(CajaIconContainer * container,FMIconView * icon_view)2634 selection_changed_callback (CajaIconContainer *container,
2635 FMIconView *icon_view)
2636 {
2637 g_assert (FM_IS_ICON_VIEW (icon_view));
2638 g_assert (container == get_icon_container (icon_view));
2639
2640 fm_directory_view_notify_selection_changed (FM_DIRECTORY_VIEW (icon_view));
2641 }
2642
2643 static void
icon_container_context_click_selection_callback(CajaIconContainer * container,GdkEventButton * event,FMIconView * icon_view)2644 icon_container_context_click_selection_callback (CajaIconContainer *container,
2645 GdkEventButton *event,
2646 FMIconView *icon_view)
2647 {
2648 g_assert (CAJA_IS_ICON_CONTAINER (container));
2649 g_assert (FM_IS_ICON_VIEW (icon_view));
2650
2651 fm_directory_view_pop_up_selection_context_menu
2652 (FM_DIRECTORY_VIEW (icon_view), event);
2653 }
2654
2655 static void
icon_container_context_click_background_callback(CajaIconContainer * container,GdkEventButton * event,FMIconView * icon_view)2656 icon_container_context_click_background_callback (CajaIconContainer *container,
2657 GdkEventButton *event,
2658 FMIconView *icon_view)
2659 {
2660 g_assert (CAJA_IS_ICON_CONTAINER (container));
2661 g_assert (FM_IS_ICON_VIEW (icon_view));
2662
2663 /* FIXME: passing event from here won't work
2664 * for gtk_menu_popup_at_pointer (in eel_pop_up_context_menu() )
2665 * if the menu is being triggered from here by the menu key
2666 */
2667 fm_directory_view_pop_up_background_context_menu
2668 (FM_DIRECTORY_VIEW (icon_view), NULL);
2669 }
2670
2671 static gboolean
fm_icon_view_react_to_icon_change_idle_callback(gpointer data)2672 fm_icon_view_react_to_icon_change_idle_callback (gpointer data)
2673 {
2674 FMIconView *icon_view;
2675
2676 g_assert (FM_IS_ICON_VIEW (data));
2677
2678 icon_view = FM_ICON_VIEW (data);
2679 icon_view->details->react_to_icon_change_idle_id = 0;
2680
2681 /* Rebuild the menus since some of them (e.g. Restore Stretched Icons)
2682 * may be different now.
2683 */
2684 fm_directory_view_update_menus (FM_DIRECTORY_VIEW (icon_view));
2685
2686 /* Don't call this again (unless rescheduled) */
2687 return FALSE;
2688 }
2689
2690 static void
icon_position_changed_callback(CajaIconContainer * container,CajaFile * file,const CajaIconPosition * position,FMIconView * icon_view)2691 icon_position_changed_callback (CajaIconContainer *container,
2692 CajaFile *file,
2693 const CajaIconPosition *position,
2694 FMIconView *icon_view)
2695 {
2696 char scale_string[G_ASCII_DTOSTR_BUF_SIZE];
2697
2698 g_assert (FM_IS_ICON_VIEW (icon_view));
2699 g_assert (container == get_icon_container (icon_view));
2700 g_assert (CAJA_IS_FILE (file));
2701
2702 /* Schedule updating menus for the next idle. Doing it directly here
2703 * noticeably slows down icon stretching. The other work here to
2704 * store the icon position and scale does not seem to noticeably
2705 * slow down icon stretching. It would be trickier to move to an
2706 * idle call, because we'd have to keep track of potentially multiple
2707 * sets of file/geometry info.
2708 */
2709 if (fm_directory_view_get_active (FM_DIRECTORY_VIEW (icon_view)) &&
2710 icon_view->details->react_to_icon_change_idle_id == 0)
2711 {
2712 icon_view->details->react_to_icon_change_idle_id
2713 = g_idle_add (fm_icon_view_react_to_icon_change_idle_callback,
2714 icon_view);
2715 }
2716
2717 /* Store the new position of the icon in the metadata. */
2718 if (!fm_icon_view_using_auto_layout (icon_view))
2719 {
2720 char *position_string;
2721
2722 position_string = g_strdup_printf
2723 ("%d,%d", position->x, position->y);
2724 caja_file_set_metadata
2725 (file, CAJA_METADATA_KEY_ICON_POSITION,
2726 NULL, position_string);
2727 g_free (position_string);
2728 }
2729
2730
2731 g_ascii_dtostr (scale_string, sizeof (scale_string), position->scale);
2732 caja_file_set_metadata
2733 (file, CAJA_METADATA_KEY_ICON_SCALE,
2734 "1.0", scale_string);
2735 }
2736
2737 /* Attempt to change the filename to the new text. Notify user if operation fails. */
2738 static void
fm_icon_view_icon_text_changed_callback(CajaIconContainer * container,CajaFile * file,char * new_name,FMIconView * icon_view)2739 fm_icon_view_icon_text_changed_callback (CajaIconContainer *container,
2740 CajaFile *file,
2741 char *new_name,
2742 FMIconView *icon_view)
2743 {
2744 g_assert (CAJA_IS_FILE (file));
2745
2746 /* Don't allow a rename with an empty string. Revert to original
2747 * without notifying the user.
2748 */
2749 if ((new_name == NULL) || (new_name[0] == '\0'))
2750 {
2751 return;
2752 }
2753 fm_rename_file (file, new_name, NULL, NULL);
2754 }
2755
2756 static char *
get_icon_uri_callback(CajaIconContainer * container,CajaFile * file,FMIconView * icon_view)2757 get_icon_uri_callback (CajaIconContainer *container,
2758 CajaFile *file,
2759 FMIconView *icon_view)
2760 {
2761 g_assert (CAJA_IS_ICON_CONTAINER (container));
2762 g_assert (CAJA_IS_FILE (file));
2763 g_assert (FM_IS_ICON_VIEW (icon_view));
2764
2765 return caja_file_get_uri (file);
2766 }
2767
2768 static char *
get_icon_drop_target_uri_callback(CajaIconContainer * container,CajaFile * file,FMIconView * icon_view)2769 get_icon_drop_target_uri_callback (CajaIconContainer *container,
2770 CajaFile *file,
2771 FMIconView *icon_view)
2772 {
2773 g_return_val_if_fail (CAJA_IS_ICON_CONTAINER (container), NULL);
2774 g_return_val_if_fail (CAJA_IS_FILE (file), NULL);
2775 g_return_val_if_fail (FM_IS_ICON_VIEW (icon_view), NULL);
2776
2777 return caja_file_get_drop_target_uri (file);
2778 }
2779
2780 /* Preferences changed callbacks */
2781 static void
fm_icon_view_text_attribute_names_changed(FMDirectoryView * directory_view)2782 fm_icon_view_text_attribute_names_changed (FMDirectoryView *directory_view)
2783 {
2784 g_assert (FM_IS_ICON_VIEW (directory_view));
2785
2786 caja_icon_container_request_update_all (get_icon_container (FM_ICON_VIEW (directory_view)));
2787 }
2788
2789 static void
fm_icon_view_embedded_text_policy_changed(FMDirectoryView * directory_view)2790 fm_icon_view_embedded_text_policy_changed (FMDirectoryView *directory_view)
2791 {
2792 g_assert (FM_IS_ICON_VIEW (directory_view));
2793
2794 caja_icon_container_request_update_all (get_icon_container (FM_ICON_VIEW (directory_view)));
2795 }
2796
2797 static void
fm_icon_view_image_display_policy_changed(FMDirectoryView * directory_view)2798 fm_icon_view_image_display_policy_changed (FMDirectoryView *directory_view)
2799 {
2800 g_assert (FM_IS_ICON_VIEW (directory_view));
2801
2802 caja_icon_container_request_update_all (get_icon_container (FM_ICON_VIEW (directory_view)));
2803 }
2804
2805 static void
fm_icon_view_click_policy_changed(FMDirectoryView * directory_view)2806 fm_icon_view_click_policy_changed (FMDirectoryView *directory_view)
2807 {
2808 g_assert (FM_IS_ICON_VIEW (directory_view));
2809
2810 fm_icon_view_update_click_mode (FM_ICON_VIEW (directory_view));
2811 }
2812
2813 static void
fm_icon_view_emblems_changed(FMDirectoryView * directory_view)2814 fm_icon_view_emblems_changed (FMDirectoryView *directory_view)
2815 {
2816 g_assert (FM_IS_ICON_VIEW (directory_view));
2817
2818 caja_icon_container_request_update_all (get_icon_container (FM_ICON_VIEW (directory_view)));
2819 }
2820
2821 static void
default_sort_order_changed_callback(gpointer callback_data)2822 default_sort_order_changed_callback (gpointer callback_data)
2823 {
2824 FMIconView *icon_view;
2825 CajaFile *file;
2826 char *sort_name;
2827 CajaIconContainer *icon_container;
2828
2829 g_return_if_fail (FM_IS_ICON_VIEW (callback_data));
2830
2831 icon_view = FM_ICON_VIEW (callback_data);
2832
2833 file = fm_directory_view_get_directory_as_file (FM_DIRECTORY_VIEW (icon_view));
2834 sort_name = fm_icon_view_get_directory_sort_by (icon_view, file);
2835 set_sort_criterion (icon_view, get_sort_criterion_by_metadata_text (sort_name));
2836 g_free (sort_name);
2837
2838 icon_container = get_icon_container (icon_view);
2839 g_return_if_fail (CAJA_IS_ICON_CONTAINER (icon_container));
2840
2841 caja_icon_container_request_update_all (icon_container);
2842 }
2843
2844 static void
default_sort_in_reverse_order_changed_callback(gpointer callback_data)2845 default_sort_in_reverse_order_changed_callback (gpointer callback_data)
2846 {
2847 FMIconView *icon_view;
2848 CajaFile *file;
2849 CajaIconContainer *icon_container;
2850
2851 g_return_if_fail (FM_IS_ICON_VIEW (callback_data));
2852
2853 icon_view = FM_ICON_VIEW (callback_data);
2854
2855 file = fm_directory_view_get_directory_as_file (FM_DIRECTORY_VIEW (icon_view));
2856 set_sort_reversed (icon_view, fm_icon_view_get_directory_sort_reversed (icon_view, file));
2857 icon_container = get_icon_container (icon_view);
2858 g_return_if_fail (CAJA_IS_ICON_CONTAINER (icon_container));
2859
2860 caja_icon_container_request_update_all (icon_container);
2861 }
2862
2863 static void
default_use_tighter_layout_changed_callback(gpointer callback_data)2864 default_use_tighter_layout_changed_callback (gpointer callback_data)
2865 {
2866 FMIconView *icon_view;
2867 CajaFile *file;
2868 CajaIconContainer *icon_container;
2869
2870 g_return_if_fail (FM_IS_ICON_VIEW (callback_data));
2871
2872 icon_view = FM_ICON_VIEW (callback_data);
2873
2874 file = fm_directory_view_get_directory_as_file (FM_DIRECTORY_VIEW (icon_view));
2875 icon_container = get_icon_container (icon_view);
2876 g_return_if_fail (CAJA_IS_ICON_CONTAINER (icon_container));
2877
2878 caja_icon_container_set_tighter_layout (
2879 icon_container,
2880 fm_icon_view_get_directory_tighter_layout (icon_view, file));
2881
2882 caja_icon_container_request_update_all (icon_container);
2883 }
2884
2885 static void
default_zoom_level_changed_callback(gpointer callback_data)2886 default_zoom_level_changed_callback (gpointer callback_data)
2887 {
2888 FMIconView *icon_view;
2889
2890 g_return_if_fail (FM_IS_ICON_VIEW (callback_data));
2891
2892 icon_view = FM_ICON_VIEW (callback_data);
2893
2894 if (fm_directory_view_supports_zooming (FM_DIRECTORY_VIEW (icon_view)))
2895 {
2896 CajaFile *file;
2897 int level;
2898
2899 file = fm_directory_view_get_directory_as_file (FM_DIRECTORY_VIEW (icon_view));
2900
2901 if (fm_icon_view_is_compact (icon_view))
2902 {
2903 level = caja_file_get_integer_metadata (file,
2904 CAJA_METADATA_KEY_COMPACT_VIEW_ZOOM_LEVEL,
2905 get_default_zoom_level (icon_view));
2906 }
2907 else
2908 {
2909 level = caja_file_get_integer_metadata (file,
2910 CAJA_METADATA_KEY_ICON_VIEW_ZOOM_LEVEL,
2911 get_default_zoom_level (icon_view));
2912 }
2913 fm_directory_view_zoom_to_level (FM_DIRECTORY_VIEW (icon_view), level);
2914 }
2915 }
2916
2917 static void
labels_beside_icons_changed_callback(gpointer callback_data)2918 labels_beside_icons_changed_callback (gpointer callback_data)
2919 {
2920 FMIconView *icon_view;
2921
2922 g_return_if_fail (FM_IS_ICON_VIEW (callback_data));
2923
2924 icon_view = FM_ICON_VIEW (callback_data);
2925
2926 set_labels_beside_icons (icon_view);
2927 }
2928
2929 static void
all_columns_same_width_changed_callback(gpointer callback_data)2930 all_columns_same_width_changed_callback (gpointer callback_data)
2931 {
2932 FMIconView *icon_view;
2933
2934 g_assert (FM_IS_ICON_VIEW (callback_data));
2935
2936 icon_view = FM_ICON_VIEW (callback_data);
2937
2938 set_columns_same_width (icon_view);
2939 }
2940
2941
2942 static void
fm_icon_view_sort_directories_first_changed(FMDirectoryView * directory_view)2943 fm_icon_view_sort_directories_first_changed (FMDirectoryView *directory_view)
2944 {
2945 FMIconView *icon_view;
2946
2947 icon_view = FM_ICON_VIEW (directory_view);
2948
2949 if (fm_icon_view_using_auto_layout (icon_view))
2950 {
2951 caja_icon_container_sort
2952 (get_icon_container (icon_view));
2953 }
2954 }
2955
2956 static gboolean
icon_view_can_accept_item(CajaIconContainer * container,CajaFile * target_item,const char * item_uri,FMDirectoryView * view)2957 icon_view_can_accept_item (CajaIconContainer *container,
2958 CajaFile *target_item,
2959 const char *item_uri,
2960 FMDirectoryView *view)
2961 {
2962 return fm_directory_view_can_accept_item (target_item, item_uri, view);
2963 }
2964
2965 static char *
icon_view_get_container_uri(CajaIconContainer * container,FMDirectoryView * view)2966 icon_view_get_container_uri (CajaIconContainer *container,
2967 FMDirectoryView *view)
2968 {
2969 return fm_directory_view_get_uri (view);
2970 }
2971
2972 static void
icon_view_move_copy_items(CajaIconContainer * container,const GList * item_uris,GArray * relative_item_points,const char * target_dir,int copy_action,int x,int y,FMDirectoryView * view)2973 icon_view_move_copy_items (CajaIconContainer *container,
2974 const GList *item_uris,
2975 GArray *relative_item_points,
2976 const char *target_dir,
2977 int copy_action,
2978 int x, int y,
2979 FMDirectoryView *view)
2980 {
2981 caja_clipboard_clear_if_colliding_uris (GTK_WIDGET (view),
2982 item_uris,
2983 fm_directory_view_get_copied_files_atom (view));
2984 fm_directory_view_move_copy_items (item_uris, relative_item_points, target_dir,
2985 copy_action, x, y, view);
2986 }
2987
2988 static void
fm_icon_view_update_click_mode(FMIconView * icon_view)2989 fm_icon_view_update_click_mode (FMIconView *icon_view)
2990 {
2991 CajaIconContainer *icon_container;
2992 int click_mode;
2993
2994 icon_container = get_icon_container (icon_view);
2995 g_assert (icon_container != NULL);
2996
2997 click_mode = g_settings_get_enum (caja_preferences, CAJA_PREFERENCES_CLICK_POLICY);
2998
2999 caja_icon_container_set_single_click_mode (icon_container,
3000 click_mode == CAJA_CLICK_POLICY_SINGLE);
3001 }
3002
3003 static gboolean
get_stored_layout_timestamp(CajaIconContainer * container,CajaIconData * icon_data,time_t * timestamp,FMIconView * view)3004 get_stored_layout_timestamp (CajaIconContainer *container,
3005 CajaIconData *icon_data,
3006 time_t *timestamp,
3007 FMIconView *view)
3008 {
3009 if (icon_data == NULL)
3010 {
3011 CajaFile *file;
3012 CajaDirectory *directory;
3013
3014 directory = fm_directory_view_get_model (FM_DIRECTORY_VIEW (view));
3015
3016 if (directory == NULL)
3017 {
3018 return FALSE;
3019 }
3020
3021 file = caja_directory_get_corresponding_file (directory);
3022 *timestamp = caja_file_get_time_metadata (file,
3023 CAJA_METADATA_KEY_ICON_VIEW_LAYOUT_TIMESTAMP);
3024 caja_file_unref (file);
3025 }
3026 else
3027 {
3028 *timestamp = caja_file_get_time_metadata (CAJA_FILE (icon_data),
3029 CAJA_METADATA_KEY_ICON_POSITION_TIMESTAMP);
3030 }
3031
3032 return TRUE;
3033 }
3034
3035 static gboolean
store_layout_timestamp(CajaIconContainer * container,CajaIconData * icon_data,const time_t * timestamp,FMIconView * view)3036 store_layout_timestamp (CajaIconContainer *container,
3037 CajaIconData *icon_data,
3038 const time_t *timestamp,
3039 FMIconView *view)
3040 {
3041 if (icon_data == NULL)
3042 {
3043 CajaFile *file;
3044 CajaDirectory *directory;
3045
3046 directory = fm_directory_view_get_model (FM_DIRECTORY_VIEW (view));
3047
3048 if (directory == NULL)
3049 {
3050 return FALSE;
3051 }
3052
3053 file = caja_directory_get_corresponding_file (directory);
3054 caja_file_set_time_metadata (file,
3055 CAJA_METADATA_KEY_ICON_VIEW_LAYOUT_TIMESTAMP,
3056 (time_t) *timestamp);
3057 caja_file_unref (file);
3058 }
3059 else
3060 {
3061 caja_file_set_time_metadata (CAJA_FILE (icon_data),
3062 CAJA_METADATA_KEY_ICON_POSITION_TIMESTAMP,
3063 (time_t) *timestamp);
3064 }
3065
3066 return TRUE;
3067 }
3068
3069 static gboolean
focus_in_event_callback(GtkWidget * widget,GdkEventFocus * event,gpointer user_data)3070 focus_in_event_callback (GtkWidget *widget, GdkEventFocus *event, gpointer user_data)
3071 {
3072 CajaWindowSlotInfo *slot_info;
3073 FMIconView *icon_view = FM_ICON_VIEW (user_data);
3074
3075 /* make the corresponding slot (and the pane that contains it) active */
3076 slot_info = fm_directory_view_get_caja_window_slot (FM_DIRECTORY_VIEW (icon_view));
3077 caja_window_slot_info_make_hosting_pane_active (slot_info);
3078
3079 return FALSE;
3080 }
3081
3082 static CajaIconContainer *
create_icon_container(FMIconView * icon_view)3083 create_icon_container (FMIconView *icon_view)
3084 {
3085 CajaIconContainer *icon_container;
3086
3087 icon_container = fm_icon_container_new (icon_view);
3088
3089 gtk_widget_set_can_focus (GTK_WIDGET (icon_container), TRUE);
3090
3091 g_signal_connect_object (icon_container, "focus_in_event",
3092 G_CALLBACK (focus_in_event_callback), icon_view, 0);
3093 g_signal_connect_object (icon_container, "activate",
3094 G_CALLBACK (icon_container_activate_callback), icon_view, 0);
3095 g_signal_connect_object (icon_container, "activate_alternate",
3096 G_CALLBACK (icon_container_activate_alternate_callback), icon_view, 0);
3097 g_signal_connect_object (icon_container, "band_select_started",
3098 G_CALLBACK (band_select_started_callback), icon_view, 0);
3099 g_signal_connect_object (icon_container, "band_select_ended",
3100 G_CALLBACK (band_select_ended_callback), icon_view, 0);
3101 g_signal_connect_object (icon_container, "context_click_selection",
3102 G_CALLBACK (icon_container_context_click_selection_callback), icon_view, 0);
3103 g_signal_connect_object (icon_container, "context_click_background",
3104 G_CALLBACK (icon_container_context_click_background_callback), icon_view, 0);
3105 g_signal_connect_object (icon_container, "icon_position_changed",
3106 G_CALLBACK (icon_position_changed_callback), icon_view, 0);
3107 g_signal_connect_object (icon_container, "icon_text_changed",
3108 G_CALLBACK (fm_icon_view_icon_text_changed_callback), icon_view, 0);
3109 g_signal_connect_object (icon_container, "selection_changed",
3110 G_CALLBACK (selection_changed_callback), icon_view, 0);
3111 /* FIXME: many of these should move into fm-icon-container as virtual methods */
3112 g_signal_connect_object (icon_container, "get_icon_uri",
3113 G_CALLBACK (get_icon_uri_callback), icon_view, 0);
3114 g_signal_connect_object (icon_container, "get_icon_drop_target_uri",
3115 G_CALLBACK (get_icon_drop_target_uri_callback), icon_view, 0);
3116 g_signal_connect_object (icon_container, "move_copy_items",
3117 G_CALLBACK (icon_view_move_copy_items), icon_view, 0);
3118 g_signal_connect_object (icon_container, "get_container_uri",
3119 G_CALLBACK (icon_view_get_container_uri), icon_view, 0);
3120 g_signal_connect_object (icon_container, "can_accept_item",
3121 G_CALLBACK (icon_view_can_accept_item), icon_view, 0);
3122 g_signal_connect_object (icon_container, "get_stored_icon_position",
3123 G_CALLBACK (get_stored_icon_position_callback), icon_view, 0);
3124 g_signal_connect_object (icon_container, "layout_changed",
3125 G_CALLBACK (layout_changed_callback), icon_view, 0);
3126 g_signal_connect_object (icon_container, "preview",
3127 G_CALLBACK (icon_container_preview_callback), icon_view, 0);
3128 g_signal_connect_object (icon_container, "renaming_icon",
3129 G_CALLBACK (renaming_icon_callback), icon_view, 0);
3130 g_signal_connect_object (icon_container, "icon_stretch_started",
3131 G_CALLBACK (fm_directory_view_update_menus), icon_view,
3132 G_CONNECT_SWAPPED);
3133 g_signal_connect_object (icon_container, "icon_stretch_ended",
3134 G_CALLBACK (fm_directory_view_update_menus), icon_view,
3135 G_CONNECT_SWAPPED);
3136
3137 g_signal_connect_object (icon_container, "get_stored_layout_timestamp",
3138 G_CALLBACK (get_stored_layout_timestamp), icon_view, 0);
3139 g_signal_connect_object (icon_container, "store_layout_timestamp",
3140 G_CALLBACK (store_layout_timestamp), icon_view, 0);
3141
3142 gtk_container_add (GTK_CONTAINER (icon_view),
3143 GTK_WIDGET (icon_container));
3144
3145 fm_icon_view_update_click_mode (icon_view);
3146
3147 gtk_widget_show (GTK_WIDGET (icon_container));
3148
3149 return icon_container;
3150 }
3151
3152 /* Handles an URL received from Mozilla */
3153 static void
icon_view_handle_netscape_url(CajaIconContainer * container,const char * encoded_url,const char * target_uri,GdkDragAction action,int x,int y,FMIconView * view)3154 icon_view_handle_netscape_url (CajaIconContainer *container, const char *encoded_url,
3155 const char *target_uri,
3156 GdkDragAction action, int x, int y, FMIconView *view)
3157 {
3158 fm_directory_view_handle_netscape_url_drop (FM_DIRECTORY_VIEW (view),
3159 encoded_url, target_uri, action, x, y);
3160 }
3161
3162 static void
icon_view_handle_uri_list(CajaIconContainer * container,const char * item_uris,const char * target_uri,GdkDragAction action,int x,int y,FMIconView * view)3163 icon_view_handle_uri_list (CajaIconContainer *container, const char *item_uris,
3164 const char *target_uri,
3165 GdkDragAction action, int x, int y, FMIconView *view)
3166 {
3167 fm_directory_view_handle_uri_list_drop (FM_DIRECTORY_VIEW (view),
3168 item_uris, target_uri, action, x, y);
3169 }
3170
3171 static void
icon_view_handle_text(CajaIconContainer * container,const char * text,const char * target_uri,GdkDragAction action,int x,int y,FMIconView * view)3172 icon_view_handle_text (CajaIconContainer *container, const char *text,
3173 const char *target_uri,
3174 GdkDragAction action, int x, int y, FMIconView *view)
3175 {
3176 fm_directory_view_handle_text_drop (FM_DIRECTORY_VIEW (view),
3177 text, target_uri, action, x, y);
3178 }
3179
3180 static void
icon_view_handle_raw(CajaIconContainer * container,const char * raw_data,int length,const char * target_uri,const char * direct_save_uri,GdkDragAction action,int x,int y,FMIconView * view)3181 icon_view_handle_raw (CajaIconContainer *container, const char *raw_data,
3182 int length, const char *target_uri, const char *direct_save_uri,
3183 GdkDragAction action, int x, int y, FMIconView *view)
3184 {
3185 fm_directory_view_handle_raw_drop (FM_DIRECTORY_VIEW (view),
3186 raw_data, length, target_uri, direct_save_uri, action, x, y);
3187 }
3188
3189 static char *
icon_view_get_first_visible_file(CajaView * view)3190 icon_view_get_first_visible_file (CajaView *view)
3191 {
3192 CajaFile *file;
3193 FMIconView *icon_view;
3194
3195 icon_view = FM_ICON_VIEW (view);
3196
3197 file = CAJA_FILE (caja_icon_container_get_first_visible_icon (get_icon_container (icon_view)));
3198
3199 if (file)
3200 {
3201 return caja_file_get_uri (file);
3202 }
3203
3204 return NULL;
3205 }
3206
3207 static void
icon_view_scroll_to_file(CajaView * view,const char * uri)3208 icon_view_scroll_to_file (CajaView *view,
3209 const char *uri)
3210 {
3211 FMIconView *icon_view;
3212
3213 icon_view = FM_ICON_VIEW (view);
3214
3215 if (uri != NULL)
3216 {
3217 CajaFile *file;
3218
3219 /* Only if existing, since we don't want to add the file to
3220 the directory if it has been removed since then */
3221 file = caja_file_get_existing_by_uri (uri);
3222 if (file != NULL)
3223 {
3224 caja_icon_container_scroll_to_icon (get_icon_container (icon_view),
3225 CAJA_ICON_CONTAINER_ICON_DATA (file));
3226 caja_file_unref (file);
3227 }
3228 }
3229 }
3230
3231 static void
fm_icon_view_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)3232 fm_icon_view_set_property (GObject *object,
3233 guint prop_id,
3234 const GValue *value,
3235 GParamSpec *pspec)
3236 {
3237 FMIconView *icon_view;
3238
3239 icon_view = FM_ICON_VIEW (object);
3240
3241 switch (prop_id)
3242 {
3243 case PROP_COMPACT:
3244 icon_view->details->compact = g_value_get_boolean (value);
3245 if (icon_view->details->compact)
3246 {
3247 caja_icon_container_set_layout_mode (get_icon_container (icon_view),
3248 gtk_widget_get_direction (GTK_WIDGET(icon_view)) == GTK_TEXT_DIR_RTL ?
3249 CAJA_ICON_LAYOUT_T_B_R_L :
3250 CAJA_ICON_LAYOUT_T_B_L_R);
3251 caja_icon_container_set_forced_icon_size (get_icon_container (icon_view),
3252 CAJA_ICON_SIZE_SMALLEST);
3253 }
3254 break;
3255
3256 default:
3257 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3258 break;
3259 }
3260 }
3261
3262
3263
3264 static void
fm_icon_view_class_init(FMIconViewClass * klass)3265 fm_icon_view_class_init (FMIconViewClass *klass)
3266 {
3267 FMDirectoryViewClass *fm_directory_view_class;
3268
3269 fm_directory_view_class = FM_DIRECTORY_VIEW_CLASS (klass);
3270
3271 G_OBJECT_CLASS (klass)->set_property = fm_icon_view_set_property;
3272 G_OBJECT_CLASS (klass)->finalize = fm_icon_view_finalize;
3273
3274 GTK_WIDGET_CLASS (klass)->destroy = fm_icon_view_destroy;
3275 GTK_WIDGET_CLASS (klass)->screen_changed = fm_icon_view_screen_changed;
3276 GTK_WIDGET_CLASS (klass)->scroll_event = fm_icon_view_scroll_event;
3277
3278 fm_directory_view_class->add_file = fm_icon_view_add_file;
3279 fm_directory_view_class->flush_added_files = fm_icon_view_flush_added_files;
3280 fm_directory_view_class->begin_loading = fm_icon_view_begin_loading;
3281 fm_directory_view_class->bump_zoom_level = fm_icon_view_bump_zoom_level;
3282 fm_directory_view_class->can_rename_file = fm_icon_view_can_rename_file;
3283 fm_directory_view_class->can_zoom_in = fm_icon_view_can_zoom_in;
3284 fm_directory_view_class->can_zoom_out = fm_icon_view_can_zoom_out;
3285 fm_directory_view_class->clear = fm_icon_view_clear;
3286 fm_directory_view_class->end_loading = fm_icon_view_end_loading;
3287 fm_directory_view_class->file_changed = fm_icon_view_file_changed;
3288 fm_directory_view_class->get_background_widget = fm_icon_view_get_background_widget;
3289 fm_directory_view_class->get_selected_icon_locations = fm_icon_view_get_selected_icon_locations;
3290 fm_directory_view_class->get_selection = fm_icon_view_get_selection;
3291 fm_directory_view_class->get_selection_for_file_transfer = fm_icon_view_get_selection;
3292 fm_directory_view_class->get_item_count = fm_icon_view_get_item_count;
3293 fm_directory_view_class->is_empty = fm_icon_view_is_empty;
3294 fm_directory_view_class->remove_file = fm_icon_view_remove_file;
3295 fm_directory_view_class->reset_to_defaults = fm_icon_view_reset_to_defaults;
3296 fm_directory_view_class->restore_default_zoom_level = fm_icon_view_restore_default_zoom_level;
3297 fm_directory_view_class->reveal_selection = fm_icon_view_reveal_selection;
3298 fm_directory_view_class->select_all = fm_icon_view_select_all;
3299 fm_directory_view_class->set_selection = fm_icon_view_set_selection;
3300 fm_directory_view_class->invert_selection = fm_icon_view_invert_selection;
3301 fm_directory_view_class->compare_files = compare_files;
3302 fm_directory_view_class->zoom_to_level = fm_icon_view_zoom_to_level;
3303 fm_directory_view_class->get_zoom_level = fm_icon_view_get_zoom_level;
3304 fm_directory_view_class->click_policy_changed = fm_icon_view_click_policy_changed;
3305 fm_directory_view_class->embedded_text_policy_changed = fm_icon_view_embedded_text_policy_changed;
3306 fm_directory_view_class->emblems_changed = fm_icon_view_emblems_changed;
3307 fm_directory_view_class->image_display_policy_changed = fm_icon_view_image_display_policy_changed;
3308 fm_directory_view_class->merge_menus = fm_icon_view_merge_menus;
3309 fm_directory_view_class->unmerge_menus = fm_icon_view_unmerge_menus;
3310 fm_directory_view_class->sort_directories_first_changed = fm_icon_view_sort_directories_first_changed;
3311 fm_directory_view_class->start_renaming_file = fm_icon_view_start_renaming_file;
3312 fm_directory_view_class->text_attribute_names_changed = fm_icon_view_text_attribute_names_changed;
3313 fm_directory_view_class->update_menus = fm_icon_view_update_menus;
3314 fm_directory_view_class->using_manual_layout = fm_icon_view_using_manual_layout;
3315 fm_directory_view_class->widget_to_file_operation_position = fm_icon_view_widget_to_file_operation_position;
3316
3317 klass->clean_up = fm_icon_view_real_clean_up;
3318 klass->supports_auto_layout = real_supports_auto_layout;
3319 klass->supports_scaling = real_supports_scaling;
3320 klass->supports_manual_layout = real_supports_manual_layout;
3321 klass->supports_keep_aligned = real_supports_keep_aligned;
3322 klass->supports_labels_beside_icons = real_supports_labels_beside_icons;
3323 klass->get_directory_auto_layout = fm_icon_view_real_get_directory_auto_layout;
3324 klass->get_directory_sort_by = fm_icon_view_real_get_directory_sort_by;
3325 klass->get_directory_sort_reversed = fm_icon_view_real_get_directory_sort_reversed;
3326 klass->get_directory_tighter_layout = fm_icon_view_real_get_directory_tighter_layout;
3327 klass->set_directory_auto_layout = fm_icon_view_real_set_directory_auto_layout;
3328 klass->set_directory_sort_by = fm_icon_view_real_set_directory_sort_by;
3329 klass->set_directory_sort_reversed = fm_icon_view_real_set_directory_sort_reversed;
3330 klass->set_directory_tighter_layout = fm_icon_view_real_set_directory_tighter_layout;
3331
3332 g_object_class_install_property (G_OBJECT_CLASS (klass),
3333 PROP_COMPACT,
3334 g_param_spec_boolean ("compact",
3335 "Compact",
3336 "Whether this view provides a compact listing",
3337 FALSE,
3338 G_PARAM_WRITABLE |
3339 G_PARAM_CONSTRUCT_ONLY));
3340
3341 }
3342
3343 static const char *
fm_icon_view_get_id(CajaView * view)3344 fm_icon_view_get_id (CajaView *view)
3345 {
3346 if (FM_IS_DESKTOP_ICON_VIEW (view))
3347 {
3348 return FM_DESKTOP_ICON_VIEW_ID;
3349 }
3350
3351 if (fm_icon_view_is_compact (FM_ICON_VIEW (view)))
3352 {
3353 return FM_COMPACT_VIEW_ID;
3354 }
3355
3356 return FM_ICON_VIEW_ID;
3357 }
3358
3359 static void
fm_icon_view_iface_init(CajaViewIface * iface)3360 fm_icon_view_iface_init (CajaViewIface *iface)
3361 {
3362 fm_directory_view_init_view_iface (iface);
3363
3364 iface->get_view_id = fm_icon_view_get_id;
3365 iface->get_first_visible_file = icon_view_get_first_visible_file;
3366 iface->scroll_to_file = icon_view_scroll_to_file;
3367 iface->get_title = NULL;
3368 }
3369
3370 static void
fm_icon_view_init(FMIconView * icon_view)3371 fm_icon_view_init (FMIconView *icon_view)
3372 {
3373 static gboolean setup_sound_preview = FALSE;
3374 CajaIconContainer *icon_container;
3375
3376 g_return_if_fail (gtk_bin_get_child (GTK_BIN (icon_view)) == NULL);
3377
3378 icon_view->details = g_new0 (FMIconViewDetails, 1);
3379 icon_view->details->sort = &sort_criteria[0];
3380 icon_view->details->filter_by_screen = FALSE;
3381
3382 icon_container = create_icon_container (icon_view);
3383
3384 /* Set our default layout mode */
3385 caja_icon_container_set_layout_mode (icon_container,
3386 gtk_widget_get_direction (GTK_WIDGET(icon_container)) == GTK_TEXT_DIR_RTL ?
3387 CAJA_ICON_LAYOUT_R_L_T_B :
3388 CAJA_ICON_LAYOUT_L_R_T_B);
3389
3390 if (!setup_sound_preview)
3391 {
3392 eel_g_settings_add_auto_enum (caja_preferences,
3393 CAJA_PREFERENCES_PREVIEW_SOUND,
3394 &preview_sound_auto_value);
3395
3396 setup_sound_preview = TRUE;
3397 }
3398
3399 g_signal_connect_swapped (caja_preferences,
3400 "changed::" CAJA_PREFERENCES_DEFAULT_SORT_ORDER,
3401 G_CALLBACK (default_sort_order_changed_callback),
3402 icon_view);
3403 g_signal_connect_swapped (caja_preferences,
3404 "changed::" CAJA_PREFERENCES_DEFAULT_SORT_IN_REVERSE_ORDER,
3405 G_CALLBACK (default_sort_in_reverse_order_changed_callback),
3406 icon_view);
3407 g_signal_connect_swapped (caja_icon_view_preferences,
3408 "changed::" CAJA_PREFERENCES_ICON_VIEW_DEFAULT_USE_TIGHTER_LAYOUT,
3409 G_CALLBACK (default_use_tighter_layout_changed_callback),
3410 icon_view);
3411 g_signal_connect_swapped (caja_icon_view_preferences,
3412 "changed::" CAJA_PREFERENCES_ICON_VIEW_DEFAULT_ZOOM_LEVEL,
3413 G_CALLBACK (default_zoom_level_changed_callback),
3414 icon_view);
3415 g_signal_connect_swapped (caja_icon_view_preferences,
3416 "changed::" CAJA_PREFERENCES_ICON_VIEW_LABELS_BESIDE_ICONS,
3417 G_CALLBACK (labels_beside_icons_changed_callback),
3418 icon_view);
3419
3420 g_signal_connect_swapped (caja_compact_view_preferences,
3421 "changed::" CAJA_PREFERENCES_COMPACT_VIEW_DEFAULT_ZOOM_LEVEL,
3422 G_CALLBACK (default_zoom_level_changed_callback),
3423 icon_view);
3424 g_signal_connect_swapped (caja_compact_view_preferences,
3425 "changed::" CAJA_PREFERENCES_COMPACT_VIEW_ALL_COLUMNS_SAME_WIDTH,
3426 G_CALLBACK (all_columns_same_width_changed_callback),
3427 icon_view);
3428
3429 g_signal_connect_object (get_icon_container (icon_view), "handle_netscape_url",
3430 G_CALLBACK (icon_view_handle_netscape_url), icon_view, 0);
3431 g_signal_connect_object (get_icon_container (icon_view), "handle_uri_list",
3432 G_CALLBACK (icon_view_handle_uri_list), icon_view, 0);
3433 g_signal_connect_object (get_icon_container (icon_view), "handle_text",
3434 G_CALLBACK (icon_view_handle_text), icon_view, 0);
3435 g_signal_connect_object (get_icon_container (icon_view), "handle_raw",
3436 G_CALLBACK (icon_view_handle_raw), icon_view, 0);
3437
3438 icon_view->details->clipboard_handler_id =
3439 g_signal_connect (caja_clipboard_monitor_get (),
3440 "clipboard_info",
3441 G_CALLBACK (icon_view_notify_clipboard_info), icon_view);
3442 }
3443
3444 static CajaView *
fm_icon_view_create(CajaWindowSlotInfo * slot)3445 fm_icon_view_create (CajaWindowSlotInfo *slot)
3446 {
3447 FMIconView *view;
3448
3449 view = g_object_new (FM_TYPE_ICON_VIEW,
3450 "window-slot", slot,
3451 "compact", FALSE,
3452 NULL);
3453
3454 gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (view)), GTK_STYLE_CLASS_VIEW);
3455
3456 return CAJA_VIEW (view);
3457 }
3458
3459 static CajaView *
fm_compact_view_create(CajaWindowSlotInfo * slot)3460 fm_compact_view_create (CajaWindowSlotInfo *slot)
3461 {
3462 FMIconView *view;
3463
3464 view = g_object_new (FM_TYPE_ICON_VIEW,
3465 "window-slot", slot,
3466 "compact", TRUE,
3467 NULL);
3468
3469 gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (view)), GTK_STYLE_CLASS_VIEW);
3470
3471 return CAJA_VIEW (view);
3472 }
3473
3474 static gboolean
fm_icon_view_supports_uri(const char * uri,GFileType file_type,const char * mime_type)3475 fm_icon_view_supports_uri (const char *uri,
3476 GFileType file_type,
3477 const char *mime_type)
3478 {
3479 if (file_type == G_FILE_TYPE_DIRECTORY)
3480 {
3481 return TRUE;
3482 }
3483 if (strcmp (mime_type, CAJA_SAVED_SEARCH_MIMETYPE) == 0)
3484 {
3485 return TRUE;
3486 }
3487 if (g_str_has_prefix (uri, "trash:"))
3488 {
3489 return TRUE;
3490 }
3491 if (g_str_has_prefix (uri, EEL_SEARCH_URI))
3492 {
3493 return TRUE;
3494 }
3495
3496 return FALSE;
3497 }
3498
3499 #define TRANSLATE_VIEW_INFO(view_info) \
3500 view_info.view_combo_label = _(view_info.view_combo_label); \
3501 view_info.view_menu_label_with_mnemonic = _(view_info.view_menu_label_with_mnemonic); \
3502 view_info.error_label = _(view_info.error_label); \
3503 view_info.startup_error_label = _(view_info.startup_error_label); \
3504 view_info.display_location_label = _(view_info.display_location_label); \
3505
3506
3507 static CajaViewInfo fm_icon_view =
3508 {
3509 .id = FM_ICON_VIEW_ID,
3510 /* Translators: this is used in the view selection dropdown
3511 * of navigation windows and in the preferences dialog */
3512 .view_combo_label = N_("Icon View"),
3513 /* Translators: this is used in the view menu */
3514 .view_menu_label_with_mnemonic = N_("_Icons"),
3515 .error_label = N_("The icon view encountered an error."),
3516 .startup_error_label = N_("The icon view encountered an error while starting up."),
3517 .display_location_label = N_("Display this location with the icon view."),
3518 .create = fm_icon_view_create,
3519 .supports_uri = fm_icon_view_supports_uri
3520 };
3521
3522 static CajaViewInfo fm_compact_view =
3523 {
3524 .id = FM_COMPACT_VIEW_ID,
3525 /* Translators: this is used in the view selection dropdown
3526 * of navigation windows and in the preferences dialog */
3527 .view_combo_label = N_("Compact View"),
3528 /* Translators: this is used in the view menu */
3529 .view_menu_label_with_mnemonic = N_("_Compact"),
3530 .error_label = N_("The compact view encountered an error."),
3531 .startup_error_label = N_("The compact view encountered an error while starting up."),
3532 .display_location_label = N_("Display this location with the compact view."),
3533 .create = fm_compact_view_create,
3534 .supports_uri = fm_icon_view_supports_uri
3535 };
3536
3537 gboolean
fm_icon_view_is_compact(FMIconView * view)3538 fm_icon_view_is_compact (FMIconView *view)
3539 {
3540 return view->details->compact;
3541 }
3542
3543 void
fm_icon_view_register(void)3544 fm_icon_view_register (void)
3545 {
3546 TRANSLATE_VIEW_INFO (fm_icon_view)
3547 caja_view_factory_register (&fm_icon_view);
3548 }
3549
3550 void
fm_compact_view_register(void)3551 fm_compact_view_register (void)
3552 {
3553 TRANSLATE_VIEW_INFO (fm_compact_view)
3554 caja_view_factory_register (&fm_compact_view);
3555 }
3556