1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
3 nautilus-file.c: Nautilus file model.
5 Copyright (C) 1999, 2000, 2001 Eazel, Inc.
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU 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.
12 This program 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 General Public License for more details.
17 You should have received a copy of the GNU General Public
18 License along with this program; if not, write to the
19 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.
22 Author: Darin Adler <darin@bentspoon.com>
26 #include "nautilus-file.h"
28 #include "nautilus-directory-metafile.h"
29 #include "nautilus-directory-notify.h"
30 #include "nautilus-directory-private.h"
31 #include "nautilus-signaller.h"
32 #include "nautilus-desktop-directory.h"
33 #include "nautilus-desktop-directory-file.h"
34 #include "nautilus-desktop-icon-file.h"
35 #include "nautilus-file-attributes.h"
36 #include "nautilus-file-private.h"
37 #include "nautilus-file-operations.h"
38 #include "nautilus-file-utilities.h"
39 #include "nautilus-global-preferences.h"
40 #include "nautilus-lib-self-check-functions.h"
41 #include "nautilus-link.h"
42 #include "nautilus-metadata.h"
43 #include "nautilus-module.h"
44 #include "nautilus-search-directory.h"
45 #include "nautilus-search-directory-file.h"
46 #include "nautilus-thumbnails.h"
47 #include "nautilus-users-groups-cache.h"
48 #include "nautilus-vfs-file.h"
49 #include "nautilus-saved-search-file.h"
50 #include <eel/eel-debug.h>
51 #include <eel/eel-glib-extensions.h>
52 #include <eel/eel-gtk-extensions.h>
53 #include <eel/eel-vfs-extensions.h>
54 #include <eel/eel-gtk-macros.h>
55 #include <eel/eel-string.h>
57 #include <gtk/gtksignal.h>
58 #include <glib/gi18n.h>
60 #include <glib/gurifuncs.h>
61 #include <libgnome/gnome-macros.h>
62 #include <glib/gfileutils.h>
63 #include <libnautilus-extension/nautilus-file-info.h>
64 #include <libxml/parser.h>
72 #include <selinux/selinux.h>
75 /* Time in seconds to cache getpwuid results */
76 #define GETPWUID_CACHE_TIME (5*60)
78 #define ICON_NAME_THUMBNAIL_LOADING "image-loading"
80 #undef NAUTILUS_FILE_DEBUG_REF
81 #undef NAUTILUS_FILE_DEBUG_REF_VALGRIND
83 #ifdef NAUTILUS_FILE_DEBUG_REF_VALGRIND
84 #include <valgrind/valgrind.h>
85 #define DEBUG_REF_PRINTF VALGRIND_PRINTF_BACKTRACE
87 #define DEBUG_REF_PRINTF printf
90 /* Files that start with these characters sort after files that don't. */
91 #define SORT_LAST_CHAR1 '.'
92 #define SORT_LAST_CHAR2 '#'
94 /* Name to use to tag metadata for the directory itself. */
95 #define FILE_NAME_FOR_DIRECTORY_METADATA "."
97 /* Name of Nautilus trash directories */
98 #define TRASH_DIRECTORY_NAME ".Trash"
101 SHOW_HIDDEN
= 1 << 0,
105 typedef void (* ModifyListFunction
) (GList
**list
, NautilusFile
*file
);
109 UPDATED_DEEP_COUNT_IN_PROGRESS
,
113 static int date_format_pref
;
115 static guint signals
[LAST_SIGNAL
];
117 static GObjectClass
*parent_class
= NULL
;
119 static GHashTable
*symbolic_links
;
121 static GQuark attribute_name_q
,
124 attribute_modification_date_q
,
125 attribute_date_modified_q
,
126 attribute_accessed_date_q
,
127 attribute_date_accessed_q
,
129 attribute_mime_type_q
,
130 attribute_size_detail_q
,
131 attribute_deep_size_q
,
132 attribute_deep_file_count_q
,
133 attribute_deep_directory_count_q
,
134 attribute_deep_total_count_q
,
135 attribute_date_changed_q
,
136 attribute_date_permissions_q
,
137 attribute_permissions_q
,
138 attribute_selinux_context_q
,
139 attribute_octal_permissions_q
,
144 attribute_link_target_q
,
146 attribute_free_space_q
;
149 static void nautilus_file_instance_init (NautilusFile
*file
);
150 static void nautilus_file_class_init (NautilusFileClass
*class);
151 static void nautilus_file_info_iface_init (NautilusFileInfoIface
*iface
);
152 static char * nautilus_file_get_owner_as_string (NautilusFile
*file
,
153 gboolean include_real_name
);
154 static char * nautilus_file_get_type_as_string (NautilusFile
*file
);
155 static gboolean
update_info_and_name (NautilusFile
*file
,
157 static const char * nautilus_file_peek_display_name (NautilusFile
*file
);
158 static const char * nautilus_file_peek_display_name_collation_key (NautilusFile
*file
);
161 nautilus_file_get_type (void)
163 static GType type
= 0;
166 const GTypeInfo info
= {
167 sizeof (NautilusFileClass
),
170 (GClassInitFunc
) nautilus_file_class_init
,
173 sizeof (NautilusFile
),
175 (GInstanceInitFunc
) nautilus_file_instance_init
,
178 const GInterfaceInfo file_info_iface_info
= {
179 (GInterfaceInitFunc
) nautilus_file_info_iface_init
,
184 type
= g_type_register_static (G_TYPE_OBJECT
,
187 g_type_add_interface_static (type
,
188 NAUTILUS_TYPE_FILE_INFO
,
189 &file_info_iface_info
);
196 nautilus_file_instance_init (NautilusFile
*file
)
198 file
->details
= G_TYPE_INSTANCE_GET_PRIVATE ((file
), NAUTILUS_TYPE_FILE
, NautilusFileDetails
);
200 nautilus_file_clear_info (file
);
201 nautilus_file_invalidate_extension_info_internal (file
);
205 nautilus_file_constructor (GType type
,
206 guint n_construct_properties
,
207 GObjectConstructParam
*construct_params
)
212 object
= (* G_OBJECT_CLASS (parent_class
)->constructor
) (type
,
213 n_construct_properties
,
216 file
= NAUTILUS_FILE (object
);
218 /* Set to default type after full construction */
219 if (NAUTILUS_FILE_GET_CLASS (file
)->default_file_type
!= G_FILE_TYPE_UNKNOWN
) {
220 file
->details
->type
= NAUTILUS_FILE_GET_CLASS (file
)->default_file_type
;
227 nautilus_file_set_display_name (NautilusFile
*file
,
228 const char *display_name
,
229 const char *edit_name
,
234 if (display_name
== NULL
|| *display_name
== 0) {
238 if (!custom
&& file
->details
->got_custom_display_name
) {
242 if (custom
&& display_name
== NULL
) {
243 /* We're re-setting a custom display name, invalidate it if
244 we already set it so that the old one is re-read */
245 if (file
->details
->got_custom_display_name
) {
246 file
->details
->got_custom_display_name
= FALSE
;
247 nautilus_file_invalidate_attributes (file
,
248 NAUTILUS_FILE_ATTRIBUTE_INFO
);
253 if (edit_name
== NULL
) {
254 edit_name
= display_name
;
259 if (eel_strcmp (eel_ref_str_peek (file
->details
->display_name
), display_name
) != 0) {
262 eel_ref_str_unref (file
->details
->display_name
);
264 if (eel_strcmp (eel_ref_str_peek (file
->details
->name
), display_name
) == 0) {
265 file
->details
->display_name
= eel_ref_str_ref (file
->details
->name
);
267 file
->details
->display_name
= eel_ref_str_new (display_name
);
270 g_free (file
->details
->display_name_collation_key
);
271 file
->details
->display_name_collation_key
= g_utf8_collate_key_for_filename (display_name
, -1);
274 if (eel_strcmp (eel_ref_str_peek (file
->details
->edit_name
), edit_name
) != 0) {
277 eel_ref_str_unref (file
->details
->edit_name
);
278 if (eel_strcmp (eel_ref_str_peek (file
->details
->display_name
), edit_name
) == 0) {
279 file
->details
->edit_name
= eel_ref_str_ref (file
->details
->display_name
);
281 file
->details
->edit_name
= eel_ref_str_new (edit_name
);
285 file
->details
->got_custom_display_name
= custom
;
290 nautilus_file_clear_info (NautilusFile
*file
)
292 file
->details
->got_file_info
= FALSE
;
293 if (file
->details
->get_info_error
) {
294 g_error_free (file
->details
->get_info_error
);
295 file
->details
->get_info_error
= NULL
;
297 /* Reset to default type, which might be other than unknown for
298 special kinds of files like the desktop or a search directory */
299 file
->details
->type
= NAUTILUS_FILE_GET_CLASS (file
)->default_file_type
;
301 if (!file
->details
->got_custom_display_name
) {
302 eel_ref_str_unref (file
->details
->display_name
);
303 file
->details
->display_name
= NULL
;
304 g_free (file
->details
->display_name_collation_key
);
305 file
->details
->display_name_collation_key
= NULL
;
306 eel_ref_str_unref (file
->details
->edit_name
);
307 file
->details
->edit_name
= NULL
;
310 if (!file
->details
->got_custom_activation_location
&&
311 file
->details
->activation_location
!= NULL
) {
312 g_object_unref (file
->details
->activation_location
);
313 file
->details
->activation_location
= NULL
;
316 if (file
->details
->icon
!= NULL
) {
317 g_object_unref (file
->details
->icon
);
318 file
->details
->icon
= NULL
;
321 g_free (file
->details
->thumbnail_path
);
322 file
->details
->thumbnail_path
= NULL
;
323 file
->details
->thumbnailing_failed
= FALSE
;
325 file
->details
->is_launcher
= FALSE
;
326 file
->details
->is_symlink
= FALSE
;
327 file
->details
->is_hidden
= FALSE
;
328 file
->details
->is_backup
= FALSE
;
329 file
->details
->is_mountpoint
= FALSE
;
330 file
->details
->uid
= -1;
331 file
->details
->gid
= -1;
332 file
->details
->can_read
= TRUE
;
333 file
->details
->can_write
= TRUE
;
334 file
->details
->can_execute
= TRUE
;
335 file
->details
->can_delete
= TRUE
;
336 file
->details
->can_trash
= TRUE
;
337 file
->details
->can_rename
= TRUE
;
338 file
->details
->can_mount
= FALSE
;
339 file
->details
->can_unmount
= FALSE
;
340 file
->details
->can_eject
= FALSE
;
341 file
->details
->has_permissions
= FALSE
;
342 file
->details
->permissions
= 0;
343 file
->details
->size
= -1;
344 file
->details
->sort_order
= 0;
345 file
->details
->mtime
= 0;
346 file
->details
->atime
= 0;
347 file
->details
->ctime
= 0;
348 g_free (file
->details
->symlink_name
);
349 file
->details
->symlink_name
= NULL
;
350 eel_ref_str_unref (file
->details
->mime_type
);
351 file
->details
->mime_type
= NULL
;
352 g_free (file
->details
->selinux_context
);
353 file
->details
->selinux_context
= NULL
;
356 static NautilusFile
*
357 nautilus_file_new_from_filename (NautilusDirectory
*directory
,
358 const char *filename
,
363 g_assert (NAUTILUS_IS_DIRECTORY (directory
));
364 g_assert (filename
!= NULL
);
365 g_assert (filename
[0] != '\0');
367 if (NAUTILUS_IS_DESKTOP_DIRECTORY (directory
)) {
369 file
= NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_DESKTOP_DIRECTORY_FILE
, NULL
));
371 /* This doesn't normally happen, unless the user somehow types in a uri
372 * that references a file like this. (See #349840) */
373 file
= NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_VFS_FILE
, NULL
));
375 } else if (NAUTILUS_IS_SEARCH_DIRECTORY (directory
)) {
377 file
= NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_SEARCH_DIRECTORY_FILE
, NULL
));
379 /* This doesn't normally happen, unless the user somehow types in a uri
380 * that references a file like this. (See #349840) */
381 file
= NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_VFS_FILE
, NULL
));
383 } else if (g_str_has_suffix (filename
, NAUTILUS_SAVED_SEARCH_EXTENSION
)) {
384 file
= NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_SAVED_SEARCH_FILE
, NULL
));
386 file
= NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_VFS_FILE
, NULL
));
389 file
->details
->directory
= nautilus_directory_ref (directory
);
391 file
->details
->name
= eel_ref_str_new (filename
);
393 #ifdef NAUTILUS_FILE_DEBUG_REF
394 DEBUG_REF_PRINTF("%10p ref'd", file
);
401 modify_link_hash_table (NautilusFile
*file
,
402 ModifyListFunction modify_function
)
406 gpointer original_key
;
409 /* Check if there is a symlink name. If none, we are OK. */
410 if (file
->details
->symlink_name
== NULL
) {
414 /* Create the hash table first time through. */
415 if (symbolic_links
== NULL
) {
416 symbolic_links
= eel_g_hash_table_new_free_at_exit
417 (g_str_hash
, g_str_equal
, "nautilus-file.c: symbolic_links");
420 target_uri
= nautilus_file_get_symbolic_link_target_uri (file
);
422 /* Find the old contents of the hash table. */
423 found
= g_hash_table_lookup_extended
424 (symbolic_links
, target_uri
,
425 &original_key
, (gpointer
*)&list_ptr
);
427 list_ptr
= g_new0 (GList
*, 1);
428 original_key
= g_strdup (target_uri
);
429 g_hash_table_insert (symbolic_links
, original_key
, list_ptr
);
431 (* modify_function
) (list_ptr
, file
);
432 if (*list_ptr
== NULL
) {
433 g_hash_table_remove (symbolic_links
, target_uri
);
435 g_free (original_key
);
441 symbolic_link_weak_notify (gpointer data
,
442 GObject
*where_the_object_was
)
445 /* This really shouldn't happen, but we're seeing some strange things in
446 bug #358172 where the symlink hashtable isn't correctly updated. */
447 *list
= g_list_remove (*list
, where_the_object_was
);
451 add_to_link_hash_table_list (GList
**list
, NautilusFile
*file
)
453 if (g_list_find (*list
, file
) != NULL
) {
454 g_warning ("Adding file to symlink_table multiple times. "
455 "Please add feedback of what you were doing at http://bugzilla.gnome.org/show_bug.cgi?id=358172\n");
458 g_object_weak_ref (G_OBJECT (file
), symbolic_link_weak_notify
, list
);
459 *list
= g_list_prepend (*list
, file
);
463 add_to_link_hash_table (NautilusFile
*file
)
465 modify_link_hash_table (file
, add_to_link_hash_table_list
);
469 remove_from_link_hash_table_list (GList
**list
, NautilusFile
*file
)
471 if (g_list_find (*list
, file
) != NULL
) {
472 g_object_weak_unref (G_OBJECT (file
), symbolic_link_weak_notify
, list
);
473 *list
= g_list_remove (*list
, file
);
478 remove_from_link_hash_table (NautilusFile
*file
)
480 modify_link_hash_table (file
, remove_from_link_hash_table_list
);
484 nautilus_file_new_from_info (NautilusDirectory
*directory
,
488 const char *mime_type
;
490 g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory
), NULL
);
491 g_return_val_if_fail (info
!= NULL
, NULL
);
493 mime_type
= g_file_info_get_content_type (info
);
495 strcmp (mime_type
, NAUTILUS_SAVED_SEARCH_MIMETYPE
) == 0) {
496 g_file_info_set_file_type (info
, G_FILE_TYPE_DIRECTORY
);
497 file
= NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_SAVED_SEARCH_FILE
, NULL
));
499 file
= NAUTILUS_FILE (g_object_new (NAUTILUS_TYPE_VFS_FILE
, NULL
));
502 file
->details
->directory
= nautilus_directory_ref (directory
);
504 update_info_and_name (file
, info
);
506 #ifdef NAUTILUS_FILE_DEBUG_REF
507 DEBUG_REF_PRINTF("%10p ref'd", file
);
513 static NautilusFile
*
514 nautilus_file_get_internal (GFile
*location
, gboolean create
)
517 NautilusDirectory
*directory
;
522 g_assert (location
!= NULL
);
524 parent
= g_file_get_parent (location
);
527 if (parent
== NULL
) {
529 parent
= g_object_ref (location
);
532 /* Get object that represents the directory. */
533 directory
= nautilus_directory_get_internal (parent
, create
);
535 g_object_unref (parent
);
537 /* Get the name for the file. */
538 if (self_owned
&& directory
!= NULL
) {
539 basename
= nautilus_directory_get_name_for_self_as_new_file (directory
);
541 basename
= g_file_get_basename (location
);
543 /* Check to see if it's a file that's already known. */
544 if (directory
== NULL
) {
546 } else if (self_owned
) {
547 file
= directory
->details
->as_file
;
549 file
= nautilus_directory_find_file_by_name (directory
, basename
);
552 /* Ref or create the file. */
554 nautilus_file_ref (file
);
556 file
= nautilus_file_new_from_filename (directory
, basename
, self_owned
);
558 g_assert (directory
->details
->as_file
== NULL
);
559 directory
->details
->as_file
= file
;
561 nautilus_directory_add_file (directory
, file
);
566 nautilus_directory_unref (directory
);
572 nautilus_file_get (GFile
*location
)
574 return nautilus_file_get_internal (location
, TRUE
);
578 nautilus_file_get_existing (GFile
*location
)
580 return nautilus_file_get_internal (location
, FALSE
);
584 nautilus_file_get_existing_by_uri (const char *uri
)
589 location
= g_file_new_for_uri (uri
);
590 file
= nautilus_file_get_internal (location
, FALSE
);
591 g_object_unref (location
);
597 nautilus_file_get_by_uri (const char *uri
)
602 location
= g_file_new_for_uri (uri
);
603 file
= nautilus_file_get_internal (location
, TRUE
);
604 g_object_unref (location
);
610 nautilus_file_is_self_owned (NautilusFile
*file
)
612 return file
->details
->directory
->details
->as_file
== file
;
616 finalize (GObject
*object
)
618 NautilusDirectory
*directory
;
622 file
= NAUTILUS_FILE (object
);
624 g_assert (file
->details
->operations_in_progress
== NULL
);
626 if (file
->details
->is_thumbnailing
) {
627 uri
= nautilus_file_get_uri (file
);
628 nautilus_thumbnail_remove_from_queue (uri
);
632 nautilus_async_destroying_file (file
);
634 remove_from_link_hash_table (file
);
636 directory
= file
->details
->directory
;
638 if (nautilus_file_is_self_owned (file
)) {
639 directory
->details
->as_file
= NULL
;
641 if (!file
->details
->is_gone
) {
642 nautilus_directory_remove_file (directory
, file
);
646 if (file
->details
->get_info_error
) {
647 g_error_free (file
->details
->get_info_error
);
650 nautilus_directory_unref (directory
);
651 eel_ref_str_unref (file
->details
->name
);
652 eel_ref_str_unref (file
->details
->display_name
);
653 g_free (file
->details
->display_name_collation_key
);
654 eel_ref_str_unref (file
->details
->edit_name
);
655 if (file
->details
->icon
) {
656 g_object_unref (file
->details
->icon
);
658 g_free (file
->details
->thumbnail_path
);
659 g_free (file
->details
->symlink_name
);
660 eel_ref_str_unref (file
->details
->mime_type
);
661 g_free (file
->details
->selinux_context
);
662 g_free (file
->details
->top_left_text
);
663 g_free (file
->details
->custom_icon
);
664 if (file
->details
->activation_location
) {
665 g_object_unref (file
->details
->activation_location
);
667 g_free (file
->details
->compare_by_emblem_cache
);
669 if (file
->details
->thumbnail
) {
670 g_object_unref (file
->details
->thumbnail
);
672 if (file
->details
->mount
) {
673 g_object_unref (file
->details
->mount
);
676 eel_g_list_free_deep (file
->details
->mime_list
);
678 eel_g_list_free_deep (file
->details
->pending_extension_emblems
);
679 eel_g_list_free_deep (file
->details
->extension_emblems
);
681 if (file
->details
->pending_extension_attributes
) {
682 g_hash_table_destroy (file
->details
->pending_extension_attributes
);
685 if (file
->details
->extension_attributes
) {
686 g_hash_table_destroy (file
->details
->extension_attributes
);
689 G_OBJECT_CLASS (parent_class
)->finalize (object
);
693 nautilus_file_ref (NautilusFile
*file
)
698 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
700 #ifdef NAUTILUS_FILE_DEBUG_REF
701 DEBUG_REF_PRINTF("%10p ref'd", file
);
704 return g_object_ref (file
);
708 nautilus_file_unref (NautilusFile
*file
)
714 g_return_if_fail (NAUTILUS_IS_FILE (file
));
716 #ifdef NAUTILUS_FILE_DEBUG_REF
717 DEBUG_REF_PRINTF("%10p unref'd", file
);
720 g_object_unref (file
);
724 * nautilus_file_get_parent_uri_for_display:
726 * Get the uri for the parent directory.
728 * @file: The file in question.
730 * Return value: A string representing the parent's location,
731 * formatted for user display (including stripping "file://").
732 * If the parent is NULL, returns the empty string.
735 nautilus_file_get_parent_uri_for_display (NautilusFile
*file
)
740 g_assert (NAUTILUS_IS_FILE (file
));
742 parent
= nautilus_file_get_parent_location (file
);
744 result
= g_file_get_parse_name (parent
);
745 g_object_unref (parent
);
747 result
= g_strdup ("");
754 * nautilus_file_get_parent_uri:
756 * Get the uri for the parent directory.
758 * @file: The file in question.
760 * Return value: A string for the parent's location, in "raw URI" form.
761 * Use nautilus_file_get_parent_uri_for_display instead if the
762 * result is to be displayed on-screen.
763 * If the parent is NULL, returns the empty string.
766 nautilus_file_get_parent_uri (NautilusFile
*file
)
768 g_assert (NAUTILUS_IS_FILE (file
));
770 if (nautilus_file_is_self_owned (file
)) {
771 /* Callers expect an empty string, not a NULL. */
772 return g_strdup ("");
775 return nautilus_directory_get_uri (file
->details
->directory
);
779 nautilus_file_get_parent_location (NautilusFile
*file
)
781 g_assert (NAUTILUS_IS_FILE (file
));
783 if (nautilus_file_is_self_owned (file
)) {
784 /* Callers expect an empty string, not a NULL. */
788 return nautilus_directory_get_location (file
->details
->directory
);
792 nautilus_file_get_parent (NautilusFile
*file
)
794 g_assert (NAUTILUS_IS_FILE (file
));
796 if (nautilus_file_is_self_owned (file
)) {
800 return nautilus_directory_get_corresponding_file (file
->details
->directory
);
804 * nautilus_file_can_read:
806 * Check whether the user is allowed to read the contents of this file.
808 * @file: The file to check.
810 * Return value: FALSE if the user is definitely not allowed to read
811 * the contents of the file. If the user has read permission, or
812 * the code can't tell whether the user has read permission,
813 * returns TRUE (so failures must always be handled).
816 nautilus_file_can_read (NautilusFile
*file
)
818 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
820 return file
->details
->can_read
;
824 * nautilus_file_can_write:
826 * Check whether the user is allowed to write to this file.
828 * @file: The file to check.
830 * Return value: FALSE if the user is definitely not allowed to write
831 * to the file. If the user has write permission, or
832 * the code can't tell whether the user has write permission,
833 * returns TRUE (so failures must always be handled).
836 nautilus_file_can_write (NautilusFile
*file
)
838 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
840 return file
->details
->can_write
;
844 * nautilus_file_can_execute:
846 * Check whether the user is allowed to execute this file.
848 * @file: The file to check.
850 * Return value: FALSE if the user is definitely not allowed to execute
851 * the file. If the user has execute permission, or
852 * the code can't tell whether the user has execute permission,
853 * returns TRUE (so failures must always be handled).
856 nautilus_file_can_execute (NautilusFile
*file
)
858 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
860 return file
->details
->can_execute
;
864 nautilus_file_can_mount (NautilusFile
*file
)
866 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
868 return file
->details
->can_mount
;
872 nautilus_file_can_unmount (NautilusFile
*file
)
874 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
876 return file
->details
->can_unmount
||
877 (file
->details
->mount
!= NULL
&&
878 g_mount_can_unmount (file
->details
->mount
));
882 nautilus_file_can_eject (NautilusFile
*file
)
884 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
886 return file
->details
->can_eject
||
887 (file
->details
->mount
!= NULL
&&
888 g_mount_can_eject (file
->details
->mount
));
892 nautilus_file_mount (NautilusFile
*file
,
893 GMountOperation
*mount_op
,
894 GCancellable
*cancellable
,
895 NautilusFileOperationCallback callback
,
896 gpointer callback_data
)
900 if (NAUTILUS_FILE_GET_CLASS (file
)->mount
== NULL
) {
903 g_set_error (&error
, G_IO_ERROR
, G_IO_ERROR_NOT_SUPPORTED
,
904 _("This file cannot be mounted"));
905 callback (file
, NULL
, error
, callback_data
);
906 g_error_free (error
);
909 NAUTILUS_FILE_GET_CLASS (file
)->mount (file
, mount_op
, cancellable
, callback
, callback_data
);
914 nautilus_file_unmount (NautilusFile
*file
)
916 if (file
->details
->can_unmount
) {
917 if (NAUTILUS_FILE_GET_CLASS (file
)->unmount
!= NULL
) {
918 NAUTILUS_FILE_GET_CLASS (file
)->unmount (file
);
920 } else if (file
->details
->mount
!= NULL
&&
921 g_mount_can_unmount (file
->details
->mount
)) {
922 nautilus_file_operations_unmount_mount (NULL
, file
->details
->mount
, FALSE
, TRUE
);
927 nautilus_file_eject (NautilusFile
*file
)
929 if (file
->details
->can_eject
) {
930 if (NAUTILUS_FILE_GET_CLASS (file
)->eject
!= NULL
) {
931 NAUTILUS_FILE_GET_CLASS (file
)->eject (file
);
933 } else if (file
->details
->mount
!= NULL
&&
934 g_mount_can_eject (file
->details
->mount
)) {
935 nautilus_file_operations_unmount_mount (NULL
, file
->details
->mount
, TRUE
, TRUE
);
940 * nautilus_file_is_desktop_directory:
942 * Check whether this file is the desktop directory.
944 * @file: The file to check.
946 * Return value: TRUE if this is the physical desktop directory.
949 nautilus_file_is_desktop_directory (NautilusFile
*file
)
953 dir
= file
->details
->directory
->details
->location
;
959 return nautilus_is_desktop_directory_file (dir
, eel_ref_str_peek (file
->details
->name
));
963 is_desktop_file (NautilusFile
*file
)
965 return nautilus_file_is_mime_type (file
, "application/x-desktop");
969 can_rename_desktop_file (NautilusFile
*file
)
974 location
= nautilus_file_get_location (file
);
975 res
= g_file_is_native (location
);
976 g_object_unref (location
);
981 * nautilus_file_can_rename:
983 * Check whether the user is allowed to change the name of the file.
985 * @file: The file to check.
987 * Return value: FALSE if the user is definitely not allowed to change
988 * the name of the file. If the user is allowed to change the name, or
989 * the code can't tell whether the user is allowed to change the name,
990 * returns TRUE (so rename failures must always be handled).
993 nautilus_file_can_rename (NautilusFile
*file
)
997 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
999 /* Nonexistent files can't be renamed. */
1000 if (nautilus_file_is_gone (file
)) {
1004 /* Self-owned files can't be renamed */
1005 if (nautilus_file_is_self_owned (file
)) {
1009 if ((is_desktop_file (file
) && !can_rename_desktop_file (file
)) ||
1010 nautilus_file_is_home (file
)) {
1016 /* Certain types of links can't be renamed */
1017 if (NAUTILUS_IS_DESKTOP_ICON_FILE (file
)) {
1018 NautilusDesktopLink
*link
;
1020 link
= nautilus_desktop_icon_file_get_link (NAUTILUS_DESKTOP_ICON_FILE (file
));
1023 can_rename
= nautilus_desktop_link_can_rename (link
);
1024 g_object_unref (link
);
1032 return file
->details
->can_rename
;
1036 nautilus_file_can_delete (NautilusFile
*file
)
1038 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
1040 /* Nonexistent files can't be deleted. */
1041 if (nautilus_file_is_gone (file
)) {
1045 /* Self-owned files can't be deleted */
1046 if (nautilus_file_is_self_owned (file
)) {
1050 return file
->details
->can_delete
;
1054 nautilus_file_can_trash (NautilusFile
*file
)
1056 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
1058 /* Nonexistent files can't be deleted. */
1059 if (nautilus_file_is_gone (file
)) {
1063 /* Self-owned files can't be deleted */
1064 if (nautilus_file_is_self_owned (file
)) {
1068 return file
->details
->can_trash
;
1072 nautilus_file_get_location (NautilusFile
*file
)
1076 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
1078 dir
= file
->details
->directory
->details
->location
;
1080 if (nautilus_file_is_self_owned (file
)) {
1081 return g_object_ref (dir
);
1084 return g_file_get_child (dir
, eel_ref_str_peek (file
->details
->name
));
1087 /* Return the actual uri associated with the passed-in file. */
1089 nautilus_file_get_uri (NautilusFile
*file
)
1094 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
1096 loc
= nautilus_file_get_location (file
);
1097 uri
= g_file_get_uri (loc
);
1098 g_object_unref (loc
);
1104 nautilus_file_get_uri_scheme (NautilusFile
*file
)
1109 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
1111 if (file
->details
->directory
== NULL
||
1112 file
->details
->directory
->details
->location
== NULL
) {
1116 loc
= nautilus_directory_get_location (file
->details
->directory
);
1117 scheme
= g_file_get_uri_scheme (loc
);
1118 g_object_unref (loc
);
1123 NautilusFileOperation
*
1124 nautilus_file_operation_new (NautilusFile
*file
,
1125 NautilusFileOperationCallback callback
,
1126 gpointer callback_data
)
1128 NautilusFileOperation
*op
;
1130 op
= g_new0 (NautilusFileOperation
, 1);
1131 op
->file
= nautilus_file_ref (file
);
1132 op
->callback
= callback
;
1133 op
->callback_data
= callback_data
;
1134 op
->cancellable
= g_cancellable_new ();
1136 op
->file
->details
->operations_in_progress
= g_list_prepend
1137 (op
->file
->details
->operations_in_progress
, op
);
1143 nautilus_file_operation_remove (NautilusFileOperation
*op
)
1145 op
->file
->details
->operations_in_progress
= g_list_remove
1146 (op
->file
->details
->operations_in_progress
, op
);
1150 nautilus_file_operation_free (NautilusFileOperation
*op
)
1152 nautilus_file_operation_remove (op
);
1153 nautilus_file_unref (op
->file
);
1154 g_object_unref (op
->cancellable
);
1155 if (op
->free_data
) {
1156 op
->free_data (op
->data
);
1162 nautilus_file_operation_complete (NautilusFileOperation
*op
, GFile
*result_file
, GError
*error
)
1164 /* Claim that something changed even if the operation failed.
1165 * This makes it easier for some clients who see the "reverting"
1166 * as "changing back".
1168 nautilus_file_operation_remove (op
);
1169 nautilus_file_changed (op
->file
);
1171 (* op
->callback
) (op
->file
, result_file
, error
, op
->callback_data
);
1173 nautilus_file_operation_free (op
);
1177 nautilus_file_operation_cancel (NautilusFileOperation
*op
)
1179 /* Cancel the operation if it's still in progress. */
1180 g_cancellable_cancel (op
->cancellable
);
1184 rename_get_info_callback (GObject
*source_object
,
1186 gpointer callback_data
)
1188 NautilusFileOperation
*op
;
1189 NautilusDirectory
*directory
;
1190 NautilusFile
*existing_file
;
1194 const char *new_name
;
1195 GFileInfo
*new_info
;
1201 new_info
= g_file_query_info_finish (G_FILE (source_object
), res
, &error
);
1202 if (new_info
!= NULL
) {
1203 directory
= op
->file
->details
->directory
;
1205 new_name
= g_file_info_get_name (new_info
);
1207 /* If there was another file by the same name in this
1208 * directory, mark it gone.
1210 existing_file
= nautilus_directory_find_file_by_name (directory
, new_name
);
1211 if (existing_file
!= NULL
) {
1212 nautilus_file_mark_gone (existing_file
);
1213 nautilus_file_changed (existing_file
);
1216 old_uri
= nautilus_file_get_uri (op
->file
);
1217 old_name
= g_strdup (eel_ref_str_peek (op
->file
->details
->name
));
1219 update_info_and_name (op
->file
, new_info
);
1221 /* Self-owned files store their metadata under the
1222 * hard-code name "." so there's no need to rename
1223 * their metadata when they are renamed.
1225 if (!nautilus_file_is_self_owned (op
->file
)) {
1226 nautilus_directory_rename_file_metadata
1227 (directory
, old_name
, eel_ref_str_peek (op
->file
->details
->name
));
1232 new_uri
= nautilus_file_get_uri (op
->file
);
1233 nautilus_directory_moved (old_uri
, new_uri
);
1237 /* the rename could have affected the display name if e.g.
1238 * we're in a vfolder where the name comes from a desktop file
1239 * and a rename affects the contents of the desktop file.
1241 if (op
->file
->details
->got_custom_display_name
) {
1242 nautilus_file_invalidate_attributes (op
->file
,
1243 NAUTILUS_FILE_ATTRIBUTE_INFO
|
1244 NAUTILUS_FILE_ATTRIBUTE_LINK_INFO
);
1247 g_object_unref (new_info
);
1249 nautilus_file_operation_complete (op
, NULL
, error
);
1251 g_error_free (error
);
1256 rename_callback (GObject
*source_object
,
1258 gpointer callback_data
)
1260 NautilusFileOperation
*op
;
1267 new_file
= g_file_set_display_name_finish (G_FILE (source_object
),
1270 if (new_file
!= NULL
) {
1271 g_file_query_info_async (new_file
,
1272 NAUTILUS_FILE_DEFAULT_ATTRIBUTES
,
1276 rename_get_info_callback
, op
);
1278 nautilus_file_operation_complete (op
, NULL
, error
);
1279 g_error_free (error
);
1284 name_is (NautilusFile
*file
, const char *new_name
)
1286 const char *old_name
;
1287 old_name
= eel_ref_str_peek (file
->details
->name
);
1288 return strcmp (new_name
, old_name
) == 0;
1292 nautilus_file_rename (NautilusFile
*file
,
1293 const char *new_name
,
1294 NautilusFileOperationCallback callback
,
1295 gpointer callback_data
)
1297 NautilusFileOperation
*op
;
1301 gboolean is_renameable_desktop_file
;
1305 g_return_if_fail (NAUTILUS_IS_FILE (file
));
1306 g_return_if_fail (new_name
!= NULL
);
1307 g_return_if_fail (callback
!= NULL
);
1309 is_renameable_desktop_file
=
1310 is_desktop_file (file
) && can_rename_desktop_file (file
);
1312 /* Return an error for incoming names containing path separators.
1313 * But not for .desktop files as '/' are allowed for them */
1314 if (strstr (new_name
, "/") != NULL
&& !is_renameable_desktop_file
) {
1315 error
= g_error_new (G_IO_ERROR
, G_IO_ERROR_INVALID_ARGUMENT
,
1316 _("Slashes are not allowed in filenames"));
1317 (* callback
) (file
, NULL
, error
, callback_data
);
1318 g_error_free (error
);
1322 /* Can't rename a file that's already gone.
1323 * We need to check this here because there may be a new
1324 * file with the same name.
1326 if (nautilus_file_is_gone (file
)) {
1327 /* Claim that something changed even if the rename
1328 * failed. This makes it easier for some clients who
1329 * see the "reverting" to the old name as "changing
1332 nautilus_file_changed (file
);
1333 error
= g_error_new (G_IO_ERROR
, G_IO_ERROR_NOT_FOUND
,
1334 _("File not found"));
1335 (* callback
) (file
, NULL
, error
, callback_data
);
1336 g_error_free (error
);
1340 /* Test the name-hasn't-changed case explicitly, for two reasons.
1341 * (1) rename returns an error if new & old are same.
1342 * (2) We don't want to send file-changed signal if nothing changed.
1344 if (name_is (file
, new_name
)) {
1345 (* callback
) (file
, NULL
, NULL
, callback_data
);
1349 /* Self-owned files can't be renamed. Test the name-not-actually-changing
1350 * case before this case.
1352 if (nautilus_file_is_self_owned (file
)) {
1353 /* Claim that something changed even if the rename
1354 * failed. This makes it easier for some clients who
1355 * see the "reverting" to the old name as "changing
1358 nautilus_file_changed (file
);
1359 error
= g_error_new (G_IO_ERROR
, G_IO_ERROR_NOT_SUPPORTED
,
1360 _("Toplevel files cannot be renamed"));
1362 (* callback
) (file
, NULL
, error
, callback_data
);
1363 g_error_free (error
);
1367 if (NAUTILUS_IS_DESKTOP_ICON_FILE (file
)) {
1368 NautilusDesktopLink
*link
;
1370 link
= nautilus_desktop_icon_file_get_link (NAUTILUS_DESKTOP_ICON_FILE (file
));
1373 nautilus_desktop_link_rename (link
, new_name
)) {
1374 (* callback
) (file
, NULL
, NULL
, callback_data
);
1376 error
= g_error_new (G_IO_ERROR
, G_IO_ERROR_FAILED
,
1377 _("Unable to rename desktop icon"));
1378 (* callback
) (file
, NULL
, error
, callback_data
);
1379 g_error_free (error
);
1382 g_object_unref (link
);
1386 if (is_renameable_desktop_file
) {
1387 /* Don't actually change the name if the new name is the same.
1388 * This helps for the vfolder method where this can happen and
1389 * we want to minimize actual changes
1391 uri
= nautilus_file_get_uri (file
);
1392 old_name
= nautilus_link_local_get_text (uri
);
1393 if (old_name
!= NULL
&& strcmp (new_name
, old_name
) == 0) {
1396 success
= nautilus_link_local_set_text (uri
, new_name
);
1402 nautilus_file_invalidate_attributes (file
,
1403 NAUTILUS_FILE_ATTRIBUTE_INFO
|
1404 NAUTILUS_FILE_ATTRIBUTE_LINK_INFO
);
1405 (* callback
) (file
, NULL
, NULL
, callback_data
);
1408 error
= g_error_new (G_IO_ERROR
, G_IO_ERROR_FAILED
,
1409 _("Unable to rename desktop file"));
1410 (* callback
) (file
, NULL
, error
, callback_data
);
1411 g_error_free (error
);
1416 /* Set up a renaming operation. */
1417 op
= nautilus_file_operation_new (file
, callback
, callback_data
);
1418 op
->is_rename
= TRUE
;
1420 /* Do the renaming. */
1422 location
= nautilus_file_get_location (file
);
1423 g_file_set_display_name_async (location
,
1429 g_object_unref (location
);
1433 nautilus_file_rename_in_progress (NautilusFile
*file
)
1436 NautilusFileOperation
*op
;
1438 for (node
= file
->details
->operations_in_progress
; node
!= NULL
; node
= node
->next
) {
1440 if (op
->is_rename
) {
1448 nautilus_file_cancel (NautilusFile
*file
,
1449 NautilusFileOperationCallback callback
,
1450 gpointer callback_data
)
1453 NautilusFileOperation
*op
;
1455 for (node
= file
->details
->operations_in_progress
; node
!= NULL
; node
= next
) {
1459 g_assert (op
->file
== file
);
1460 if (op
->callback
== callback
&& op
->callback_data
== callback_data
) {
1461 nautilus_file_operation_cancel (op
);
1467 nautilus_file_matches_uri (NautilusFile
*file
, const char *match_uri
)
1469 GFile
*match_file
, *location
;
1472 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
1473 g_return_val_if_fail (match_uri
!= NULL
, FALSE
);
1475 location
= nautilus_file_get_location (file
);
1476 match_file
= g_file_new_for_uri (match_uri
);
1477 result
= g_file_equal (location
, match_file
);
1478 g_object_unref (location
);
1479 g_object_unref (match_file
);
1485 nautilus_file_is_local (NautilusFile
*file
)
1487 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
1489 return nautilus_directory_is_local (file
->details
->directory
);
1493 update_link (NautilusFile
*link_file
, NautilusFile
*target_file
)
1495 g_assert (NAUTILUS_IS_FILE (link_file
));
1496 g_assert (NAUTILUS_IS_FILE (target_file
));
1498 /* FIXME bugzilla.gnome.org 42044: If we don't put any code
1499 * here then the hash table is a waste of time.
1504 get_link_files (NautilusFile
*target_file
)
1509 if (symbolic_links
== NULL
) {
1512 uri
= nautilus_file_get_uri (target_file
);
1513 link_files
= g_hash_table_lookup (symbolic_links
, uri
);
1517 return nautilus_file_list_copy (*link_files
);
1523 update_links_if_target (NautilusFile
*target_file
)
1525 GList
*link_files
, *p
;
1527 link_files
= get_link_files (target_file
);
1528 for (p
= link_files
; p
!= NULL
; p
= p
->next
) {
1529 update_link (NAUTILUS_FILE (p
->data
), target_file
);
1531 nautilus_file_list_free (link_files
);
1535 update_info_internal (NautilusFile
*file
,
1537 gboolean update_name
)
1541 gboolean is_symlink
, is_hidden
, is_backup
, is_mountpoint
;
1542 gboolean has_permissions
;
1543 guint32 permissions
;
1544 gboolean can_read
, can_write
, can_execute
, can_delete
, can_trash
, can_rename
, can_mount
, can_unmount
, can_eject
;
1545 gboolean thumbnailing_failed
;
1549 time_t atime
, mtime
, ctime
;
1550 const char *symlink_name
, *mime_type
, *selinux_context
, *name
, *thumbnail_path
;
1551 GFileType file_type
;
1553 GFile
*old_activation_location
;
1554 const char *activation_uri
;
1555 const char *description
;
1557 if (file
->details
->is_gone
) {
1562 nautilus_file_mark_gone (file
);
1566 file
->details
->file_info_is_up_to_date
= TRUE
;
1568 /* FIXME bugzilla.gnome.org 42044: Need to let links that
1569 * point to the old name know that the file has been renamed.
1572 remove_from_link_hash_table (file
);
1576 if (!file
->details
->got_file_info
) {
1579 file
->details
->got_file_info
= TRUE
;
1581 changed
|= nautilus_file_set_display_name (file
,
1582 g_file_info_get_display_name (info
),
1583 g_file_info_get_edit_name (info
),
1586 file_type
= g_file_info_get_file_type (info
);
1587 if (file
->details
->type
!= file_type
) {
1590 file
->details
->type
= file_type
;
1592 if (!file
->details
->got_custom_activation_location
) {
1593 activation_uri
= g_file_info_get_attribute_string (info
, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI
);
1594 if (activation_uri
== NULL
) {
1595 if (file
->details
->activation_location
) {
1596 g_object_unref (file
->details
->activation_location
);
1597 file
->details
->activation_location
= NULL
;
1601 old_activation_location
= file
->details
->activation_location
;
1602 file
->details
->activation_location
= g_file_new_for_uri (activation_uri
);
1604 if (old_activation_location
) {
1605 if (!g_file_equal (old_activation_location
,
1606 file
->details
->activation_location
)) {
1609 g_object_unref (old_activation_location
);
1616 is_symlink
= g_file_info_get_is_symlink (info
);
1617 if (file
->details
->is_symlink
!= is_symlink
) {
1620 file
->details
->is_symlink
= is_symlink
;
1622 is_hidden
= g_file_info_get_is_hidden (info
);
1623 if (file
->details
->is_hidden
!= is_hidden
) {
1626 file
->details
->is_hidden
= is_hidden
;
1628 is_backup
= g_file_info_get_is_backup (info
);
1629 if (file
->details
->is_backup
!= is_backup
) {
1632 file
->details
->is_backup
= is_backup
;
1634 is_mountpoint
= g_file_info_get_attribute_boolean (info
, G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT
);
1635 if (file
->details
->is_mountpoint
!= is_mountpoint
) {
1638 file
->details
->is_mountpoint
= is_mountpoint
;
1640 has_permissions
= g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_UNIX_MODE
);
1641 permissions
= g_file_info_get_attribute_uint32 (info
, G_FILE_ATTRIBUTE_UNIX_MODE
);;
1642 if (file
->details
->has_permissions
!= has_permissions
||
1643 file
->details
->permissions
!= permissions
) {
1646 file
->details
->has_permissions
= has_permissions
;
1647 file
->details
->permissions
= permissions
;
1649 /* We default to TRUE for this if we can't know */
1657 can_unmount
= FALSE
;
1659 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_ACCESS_CAN_READ
)) {
1660 can_read
= g_file_info_get_attribute_boolean (info
,
1661 G_FILE_ATTRIBUTE_ACCESS_CAN_READ
);
1663 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE
)) {
1664 can_write
= g_file_info_get_attribute_boolean (info
,
1665 G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE
);
1667 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE
)) {
1668 can_execute
= g_file_info_get_attribute_boolean (info
,
1669 G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE
);
1671 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE
)) {
1672 can_delete
= g_file_info_get_attribute_boolean (info
,
1673 G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE
);
1675 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH
)) {
1676 can_trash
= g_file_info_get_attribute_boolean (info
,
1677 G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH
);
1679 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME
)) {
1680 can_rename
= g_file_info_get_attribute_boolean (info
,
1681 G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME
);
1683 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT
)) {
1684 can_mount
= g_file_info_get_attribute_boolean (info
,
1685 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT
);
1687 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT
)) {
1688 can_unmount
= g_file_info_get_attribute_boolean (info
,
1689 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT
);
1691 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT
)) {
1692 can_eject
= g_file_info_get_attribute_boolean (info
,
1693 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT
);
1695 if (file
->details
->can_read
!= can_read
||
1696 file
->details
->can_write
!= can_write
||
1697 file
->details
->can_execute
!= can_execute
||
1698 file
->details
->can_delete
!= can_delete
||
1699 file
->details
->can_trash
!= can_trash
||
1700 file
->details
->can_rename
!= can_rename
||
1701 file
->details
->can_mount
!= can_mount
||
1702 file
->details
->can_unmount
!= can_unmount
||
1703 file
->details
->can_eject
!= can_eject
) {
1707 file
->details
->can_read
= can_read
;
1708 file
->details
->can_write
= can_write
;
1709 file
->details
->can_execute
= can_execute
;
1710 file
->details
->can_delete
= can_delete
;
1711 file
->details
->can_trash
= can_trash
;
1712 file
->details
->can_rename
= can_rename
;
1713 file
->details
->can_mount
= can_mount
;
1714 file
->details
->can_unmount
= can_unmount
;
1715 file
->details
->can_eject
= can_eject
;
1719 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_UNIX_UID
)) {
1720 uid
= g_file_info_get_attribute_uint32 (info
, G_FILE_ATTRIBUTE_UNIX_UID
);
1722 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_UNIX_GID
)) {
1723 gid
= g_file_info_get_attribute_uint32 (info
, G_FILE_ATTRIBUTE_UNIX_GID
);
1725 if (file
->details
->uid
!= uid
||
1726 file
->details
->gid
!= gid
) {
1729 file
->details
->uid
= uid
;
1730 file
->details
->gid
= gid
;
1733 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_STANDARD_SIZE
)) {
1734 size
= g_file_info_get_size (info
);
1736 if (file
->details
->size
!= size
) {
1739 file
->details
->size
= size
;
1741 sort_order
= g_file_info_get_sort_order (info
);
1742 if (file
->details
->sort_order
!= sort_order
) {
1745 file
->details
->sort_order
= sort_order
;
1747 atime
= g_file_info_get_attribute_uint64 (info
, G_FILE_ATTRIBUTE_TIME_ACCESS
);
1748 ctime
= g_file_info_get_attribute_uint64 (info
, G_FILE_ATTRIBUTE_TIME_CHANGED
);
1749 mtime
= g_file_info_get_attribute_uint64 (info
, G_FILE_ATTRIBUTE_TIME_MODIFIED
);
1750 if (file
->details
->atime
!= atime
||
1751 file
->details
->mtime
!= mtime
||
1752 file
->details
->ctime
!= ctime
) {
1755 file
->details
->atime
= atime
;
1756 file
->details
->ctime
= ctime
;
1757 file
->details
->mtime
= mtime
;
1759 if (file
->details
->thumbnail
!= NULL
&&
1760 file
->details
->thumbnail_mtime
!= 0 &&
1761 file
->details
->thumbnail_mtime
!= mtime
) {
1762 file
->details
->thumbnail_is_up_to_date
= FALSE
;
1766 icon
= g_file_info_get_icon (info
);
1767 if (!g_icon_equal (icon
, file
->details
->icon
)) {
1770 if (file
->details
->icon
) {
1771 g_object_unref (file
->details
->icon
);
1773 file
->details
->icon
= g_object_ref (icon
);
1776 thumbnail_path
= g_file_info_get_attribute_byte_string (info
, G_FILE_ATTRIBUTE_THUMBNAIL_PATH
);
1777 if (eel_strcmp (file
->details
->thumbnail_path
, thumbnail_path
) != 0) {
1779 g_free (file
->details
->thumbnail_path
);
1780 file
->details
->thumbnail_path
= g_strdup (thumbnail_path
);
1783 thumbnailing_failed
= g_file_info_get_attribute_boolean (info
, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED
);
1784 if (file
->details
->thumbnailing_failed
!= thumbnailing_failed
) {
1786 file
->details
->thumbnailing_failed
= thumbnailing_failed
;
1789 symlink_name
= g_file_info_get_symlink_target (info
);
1790 if (eel_strcmp (file
->details
->symlink_name
, symlink_name
) != 0) {
1792 g_free (file
->details
->symlink_name
);
1793 file
->details
->symlink_name
= g_strdup (symlink_name
);
1796 mime_type
= g_file_info_get_content_type (info
);
1797 if (eel_strcmp (eel_ref_str_peek (file
->details
->mime_type
), mime_type
) != 0) {
1800 eel_ref_str_unref (file
->details
->mime_type
);
1801 file
->details
->mime_type
= eel_ref_str_get_unique (mime_type
);
1803 selinux_context
= g_file_info_get_attribute_string (info
, G_FILE_ATTRIBUTE_SELINUX_CONTEXT
);
1804 if (eel_strcmp (file
->details
->selinux_context
, selinux_context
) != 0) {
1806 g_free (file
->details
->selinux_context
);
1807 file
->details
->selinux_context
= g_strdup (selinux_context
);
1810 description
= g_file_info_get_attribute_string (info
, G_FILE_ATTRIBUTE_STANDARD_DESCRIPTION
);
1811 if (eel_strcmp (file
->details
->description
, description
) != 0) {
1813 g_free (file
->details
->description
);
1814 file
->details
->description
= g_strdup (description
);
1818 name
= g_file_info_get_name (info
);
1819 if (file
->details
->name
== NULL
||
1820 strcmp (eel_ref_str_peek (file
->details
->name
), name
) != 0) {
1821 node
= nautilus_directory_begin_file_name_change
1822 (file
->details
->directory
, file
);
1824 eel_ref_str_unref (file
->details
->name
);
1825 if (eel_strcmp (eel_ref_str_peek (file
->details
->display_name
),
1827 file
->details
->name
= eel_ref_str_ref (file
->details
->display_name
);
1829 file
->details
->name
= eel_ref_str_new (name
);
1832 nautilus_directory_end_file_name_change
1833 (file
->details
->directory
, file
, node
);
1838 add_to_link_hash_table (file
);
1840 update_links_if_target (file
);
1847 update_info_and_name (NautilusFile
*file
,
1850 return update_info_internal (file
, info
, TRUE
);
1854 nautilus_file_update_info (NautilusFile
*file
,
1857 return update_info_internal (file
, info
, FALSE
);
1861 update_name_internal (NautilusFile
*file
,
1863 gboolean in_directory
)
1867 g_assert (name
!= NULL
);
1869 if (file
->details
->is_gone
) {
1873 if (name_is (file
, name
)) {
1879 node
= nautilus_directory_begin_file_name_change
1880 (file
->details
->directory
, file
);
1883 eel_ref_str_unref (file
->details
->name
);
1884 file
->details
->name
= eel_ref_str_new (name
);
1887 nautilus_directory_end_file_name_change
1888 (file
->details
->directory
, file
, node
);
1895 nautilus_file_update_name (NautilusFile
*file
, const char *name
)
1899 ret
= update_name_internal (file
, name
, TRUE
);
1902 update_links_if_target (file
);
1909 nautilus_file_update_name_and_directory (NautilusFile
*file
,
1911 NautilusDirectory
*new_directory
)
1913 NautilusDirectory
*old_directory
;
1914 FileMonitors
*monitors
;
1916 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
1917 g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (file
->details
->directory
), FALSE
);
1918 g_return_val_if_fail (!file
->details
->is_gone
, FALSE
);
1919 g_return_val_if_fail (!nautilus_file_is_self_owned (file
), FALSE
);
1920 g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (new_directory
), FALSE
);
1922 old_directory
= file
->details
->directory
;
1923 if (old_directory
== new_directory
) {
1925 return update_name_internal (file
, name
, TRUE
);
1931 nautilus_file_ref (file
);
1933 /* FIXME bugzilla.gnome.org 42044: Need to let links that
1934 * point to the old name know that the file has been moved.
1937 remove_from_link_hash_table (file
);
1939 monitors
= nautilus_directory_remove_file_monitors (old_directory
, file
);
1940 nautilus_directory_remove_file (old_directory
, file
);
1942 file
->details
->directory
= nautilus_directory_ref (new_directory
);
1943 nautilus_directory_unref (old_directory
);
1946 update_name_internal (file
, name
, FALSE
);
1949 nautilus_directory_add_file (new_directory
, file
);
1950 nautilus_directory_add_file_monitors (new_directory
, file
, monitors
);
1952 add_to_link_hash_table (file
);
1954 update_links_if_target (file
);
1956 nautilus_file_unref (file
);
1962 nautilus_file_set_directory (NautilusFile
*file
,
1963 NautilusDirectory
*new_directory
)
1965 nautilus_file_update_name_and_directory (file
, NULL
, new_directory
);
1969 get_item_count (NautilusFile
*file
,
1972 gboolean known
, unreadable
;
1974 known
= nautilus_file_get_directory_item_count
1975 (file
, count
, &unreadable
);
1986 get_size (NautilusFile
*file
,
1989 /* If we tried and failed, then treat it like there is no size
1992 if (file
->details
->get_info_failed
) {
1996 /* If the info is NULL that means we haven't even tried yet,
1997 * so it's just unknown, not unknowable.
1999 if (!file
->details
->got_file_info
) {
2003 /* If we got info with no size in it, it means there is no
2004 * such thing as a size as far as gnome-vfs is concerned,
2007 if (file
->details
->size
== -1) {
2011 /* We have a size! */
2012 *size
= file
->details
->size
;
2017 get_time (NautilusFile
*file
,
2019 NautilusDateType type
)
2023 /* If we tried and failed, then treat it like there is no size
2026 if (file
->details
->get_info_failed
) {
2030 /* If the info is NULL that means we haven't even tried yet,
2031 * so it's just unknown, not unknowable.
2033 if (!file
->details
->got_file_info
) {
2039 case NAUTILUS_DATE_TYPE_MODIFIED
:
2040 time
= file
->details
->mtime
;
2042 case NAUTILUS_DATE_TYPE_ACCESSED
:
2043 time
= file
->details
->atime
;
2046 g_assert_not_reached ();
2052 /* If we got info with no modification time in it, it means
2053 * there is no such thing as a modification time as far as
2054 * gnome-vfs is concerned, so "unknowable".
2063 compare_directories_by_count (NautilusFile
*file_1
, NautilusFile
*file_2
)
2066 * Directories with unknown # of items
2067 * Directories with "unknowable" # of items
2068 * Directories with 0 items
2069 * Directories with n items
2072 Knowledge count_known_1
, count_known_2
;
2073 guint count_1
, count_2
;
2075 count_known_1
= get_item_count (file_1
, &count_1
);
2076 count_known_2
= get_item_count (file_2
, &count_2
);
2078 if (count_known_1
> count_known_2
) {
2081 if (count_known_1
< count_known_2
) {
2085 /* count_known_1 and count_known_2 are equal now. Check if count
2086 * details are UNKNOWABLE or UNKNOWN.
2088 if (count_known_1
== UNKNOWABLE
|| count_known_1
== UNKNOWN
) {
2092 if (count_1
< count_2
) {
2095 if (count_1
> count_2
) {
2103 compare_files_by_size (NautilusFile
*file_1
, NautilusFile
*file_2
)
2106 * Files with unknown size.
2107 * Files with "unknowable" size.
2108 * Files with smaller sizes.
2109 * Files with large sizes.
2112 Knowledge size_known_1
, size_known_2
;
2113 goffset size_1
, size_2
;
2115 size_known_1
= get_size (file_1
, &size_1
);
2116 size_known_2
= get_size (file_2
, &size_2
);
2118 if (size_known_1
> size_known_2
) {
2121 if (size_known_1
< size_known_2
) {
2125 /* size_known_1 and size_known_2 are equal now. Check if size
2126 * details are UNKNOWABLE or UNKNOWN
2128 if (size_known_1
== UNKNOWABLE
|| size_known_1
== UNKNOWN
) {
2132 if (size_1
< size_2
) {
2135 if (size_1
> size_2
) {
2143 compare_by_size (NautilusFile
*file_1
, NautilusFile
*file_2
)
2146 * Directories with n items
2147 * Directories with 0 items
2148 * Directories with "unknowable" # of items
2149 * Directories with unknown # of items
2150 * Files with large sizes.
2151 * Files with smaller sizes.
2152 * Files with "unknowable" size.
2153 * Files with unknown size.
2156 gboolean is_directory_1
, is_directory_2
;
2158 is_directory_1
= nautilus_file_is_directory (file_1
);
2159 is_directory_2
= nautilus_file_is_directory (file_2
);
2161 if (is_directory_1
&& !is_directory_2
) {
2164 if (is_directory_2
&& !is_directory_1
) {
2168 if (is_directory_1
) {
2169 return compare_directories_by_count (file_1
, file_2
);
2171 return compare_files_by_size (file_1
, file_2
);
2176 compare_by_display_name (NautilusFile
*file_1
, NautilusFile
*file_2
)
2178 const char *name_1
, *name_2
;
2179 const char *key_1
, *key_2
;
2180 gboolean sort_last_1
, sort_last_2
;
2183 name_1
= nautilus_file_peek_display_name (file_1
);
2184 name_2
= nautilus_file_peek_display_name (file_2
);
2186 sort_last_1
= name_1
[0] == SORT_LAST_CHAR1
|| name_1
[0] == SORT_LAST_CHAR2
;
2187 sort_last_2
= name_2
[0] == SORT_LAST_CHAR1
|| name_2
[0] == SORT_LAST_CHAR2
;
2189 if (sort_last_1
&& !sort_last_2
) {
2191 } else if (!sort_last_1
&& sort_last_2
) {
2194 key_1
= nautilus_file_peek_display_name_collation_key (file_1
);
2195 key_2
= nautilus_file_peek_display_name_collation_key (file_2
);
2196 compare
= strcmp (key_1
, key_2
);
2203 compare_by_directory_name (NautilusFile
*file_1
, NautilusFile
*file_2
)
2205 char *directory_1
, *directory_2
;
2208 if (file_1
->details
->directory
== file_2
->details
->directory
) {
2212 directory_1
= nautilus_file_get_parent_uri_for_display (file_1
);
2213 directory_2
= nautilus_file_get_parent_uri_for_display (file_2
);
2215 compare
= g_utf8_collate (directory_1
, directory_2
);
2217 g_free (directory_1
);
2218 g_free (directory_2
);
2224 file_has_note (NautilusFile
*file
)
2229 note
= nautilus_file_get_metadata (file
, NAUTILUS_METADATA_KEY_ANNOTATION
, NULL
);
2230 res
= note
!= NULL
&& note
[0] != 0;
2237 prepend_automatic_keywords (NautilusFile
*file
,
2240 /* Prepend in reverse order. */
2241 NautilusFile
*parent
;
2243 parent
= nautilus_file_get_parent (file
);
2245 #ifdef TRASH_IS_FAST_ENOUGH
2246 if (nautilus_file_is_in_trash (file
)) {
2247 names
= g_list_prepend
2248 (names
, g_strdup (NAUTILUS_FILE_EMBLEM_NAME_TRASH
));
2251 if (nautilus_file_is_desktop_directory (file
)) {
2252 names
= g_list_prepend
2253 (names
, g_strdup (NAUTILUS_FILE_EMBLEM_NAME_DESKTOP
));
2255 if (file_has_note (file
)) {
2256 names
= g_list_prepend
2257 (names
, g_strdup (NAUTILUS_FILE_EMBLEM_NAME_NOTE
));
2259 if (!nautilus_file_can_write (file
) &&
2260 (parent
== NULL
|| nautilus_file_can_write (parent
))) {
2261 names
= g_list_prepend
2262 (names
, g_strdup (NAUTILUS_FILE_EMBLEM_NAME_CANT_WRITE
));
2264 if (!nautilus_file_can_read (file
)) {
2265 names
= g_list_prepend
2266 (names
, g_strdup (NAUTILUS_FILE_EMBLEM_NAME_CANT_READ
));
2268 if (nautilus_file_is_symbolic_link (file
)) {
2269 names
= g_list_prepend
2270 (names
, g_strdup (NAUTILUS_FILE_EMBLEM_NAME_SYMBOLIC_LINK
));
2274 nautilus_file_unref (parent
);
2282 fill_emblem_cache_if_needed (NautilusFile
*file
)
2284 GList
*node
, *keywords
;
2288 if (file
->details
->compare_by_emblem_cache
!= NULL
) {
2289 /* Got a cache already. */
2293 keywords
= nautilus_file_get_keywords (file
);
2295 /* Add up the keyword string lengths */
2297 for (node
= keywords
; node
!= NULL
; node
= node
->next
) {
2298 length
+= strlen ((const char *) node
->data
) + 1;
2301 /* Now that we know how large the cache struct needs to be, allocate it. */
2302 file
->details
->compare_by_emblem_cache
= g_malloc (sizeof(NautilusFileSortByEmblemCache
) + length
);
2304 /* Copy them into the cache. */
2305 scanner
= file
->details
->compare_by_emblem_cache
->emblem_keywords
;
2306 for (node
= keywords
; node
!= NULL
; node
= node
->next
) {
2307 length
= strlen ((const char *) node
->data
) + 1;
2308 memcpy (scanner
, (const char *) node
->data
, length
);
2312 /* Zero-terminate so we can tell where the list ends. */
2315 eel_g_list_free_deep (keywords
);
2319 compare_by_emblems (NautilusFile
*file_1
, NautilusFile
*file_2
)
2321 const char *keyword_cache_1
, *keyword_cache_2
;
2325 fill_emblem_cache_if_needed (file_1
);
2326 fill_emblem_cache_if_needed (file_2
);
2328 /* We ignore automatic emblems, and only sort by user-added keywords. */
2330 keyword_cache_1
= file_1
->details
->compare_by_emblem_cache
->emblem_keywords
;
2331 keyword_cache_2
= file_2
->details
->compare_by_emblem_cache
->emblem_keywords
;
2332 for (; *keyword_cache_1
!= '\0' && *keyword_cache_2
!= '\0';) {
2333 compare_result
= g_utf8_collate (keyword_cache_1
, keyword_cache_2
);
2334 if (compare_result
!= 0) {
2335 return compare_result
;
2338 /* Advance to the next keyword */
2339 length
= strlen (keyword_cache_1
);
2340 keyword_cache_1
+= length
+ 1;
2341 keyword_cache_2
+= length
+ 1;
2345 /* One or both is now NULL. */
2346 if (*keyword_cache_1
!= '\0') {
2347 g_assert (*keyword_cache_2
== '\0');
2349 } else if (*keyword_cache_2
!= '\0') {
2357 compare_by_type (NautilusFile
*file_1
, NautilusFile
*file_2
)
2359 gboolean is_directory_1
;
2360 gboolean is_directory_2
;
2361 char *type_string_1
;
2362 char *type_string_2
;
2365 /* Directories go first. Then, if mime types are identical,
2366 * don't bother getting strings (for speed). This assumes
2367 * that the string is dependent entirely on the mime type,
2368 * which is true now but might not be later.
2370 is_directory_1
= nautilus_file_is_directory (file_1
);
2371 is_directory_2
= nautilus_file_is_directory (file_2
);
2373 if (is_directory_1
&& is_directory_2
) {
2377 if (is_directory_1
) {
2381 if (is_directory_2
) {
2385 if (file_1
->details
->mime_type
!= NULL
&&
2386 file_2
->details
->mime_type
!= NULL
&&
2387 strcmp (eel_ref_str_peek (file_1
->details
->mime_type
),
2388 eel_ref_str_peek (file_2
->details
->mime_type
)) == 0) {
2392 type_string_1
= nautilus_file_get_type_as_string (file_1
);
2393 type_string_2
= nautilus_file_get_type_as_string (file_2
);
2395 result
= g_utf8_collate (type_string_1
, type_string_2
);
2397 g_free (type_string_1
);
2398 g_free (type_string_2
);
2404 compare_by_time (NautilusFile
*file_1
, NautilusFile
*file_2
, NautilusDateType type
)
2407 * Files with unknown times.
2408 * Files with "unknowable" times.
2409 * Files with older times.
2410 * Files with newer times.
2413 Knowledge time_known_1
, time_known_2
;
2414 time_t time_1
, time_2
;
2419 time_known_1
= get_time (file_1
, &time_1
, type
);
2420 time_known_2
= get_time (file_2
, &time_2
, type
);
2422 if (time_known_1
> time_known_2
) {
2425 if (time_known_1
< time_known_2
) {
2429 /* Now time_known_1 is equal to time_known_2. Check whether
2430 * we failed to get modification times for files
2432 if(time_known_1
== UNKNOWABLE
|| time_known_1
== UNKNOWN
) {
2436 if (time_1
< time_2
) {
2439 if (time_1
> time_2
) {
2447 compare_by_full_path (NautilusFile
*file_1
, NautilusFile
*file_2
)
2451 compare
= compare_by_directory_name (file_1
, file_2
);
2455 return compare_by_display_name (file_1
, file_2
);
2459 nautilus_file_compare_for_sort_internal (NautilusFile
*file_1
,
2460 NautilusFile
*file_2
,
2461 gboolean directories_first
)
2463 gboolean is_directory_1
, is_directory_2
;
2465 if (directories_first
) {
2466 is_directory_1
= nautilus_file_is_directory (file_1
);
2467 is_directory_2
= nautilus_file_is_directory (file_2
);
2469 if (is_directory_1
&& !is_directory_2
) {
2473 if (is_directory_2
&& !is_directory_1
) {
2478 if (file_1
->details
->sort_order
< file_2
->details
->sort_order
) {
2480 } else if (file_1
->details
->sort_order
> file_2
->details
->sort_order
) {
2488 * nautilus_file_compare_for_sort:
2489 * @file_1: A file object
2490 * @file_2: Another file object
2491 * @sort_type: Sort criterion
2492 * @directories_first: Put all directories before any non-directories
2493 * @reversed: Reverse the order of the items, except that
2494 * the directories_first flag is still respected.
2496 * Return value: int < 0 if @file_1 should come before file_2 in a
2497 * sorted list; int > 0 if @file_2 should come before file_1 in a
2498 * sorted list; 0 if @file_1 and @file_2 are equal for this sort criterion. Note
2499 * that each named sort type may actually break ties several ways, with the name
2500 * of the sort criterion being the primary but not only differentiator.
2503 nautilus_file_compare_for_sort (NautilusFile
*file_1
,
2504 NautilusFile
*file_2
,
2505 NautilusFileSortType sort_type
,
2506 gboolean directories_first
,
2511 if (file_1
== file_2
) {
2515 result
= nautilus_file_compare_for_sort_internal (file_1
, file_2
, directories_first
);
2518 switch (sort_type
) {
2519 case NAUTILUS_FILE_SORT_BY_DISPLAY_NAME
:
2520 result
= compare_by_display_name (file_1
, file_2
);
2522 result
= compare_by_directory_name (file_1
, file_2
);
2525 case NAUTILUS_FILE_SORT_BY_DIRECTORY
:
2526 result
= compare_by_full_path (file_1
, file_2
);
2528 case NAUTILUS_FILE_SORT_BY_SIZE
:
2529 /* Compare directory sizes ourselves, then if necessary
2530 * use GnomeVFS to compare file sizes.
2532 result
= compare_by_size (file_1
, file_2
);
2534 result
= compare_by_full_path (file_1
, file_2
);
2537 case NAUTILUS_FILE_SORT_BY_TYPE
:
2538 /* GnomeVFS doesn't know about our special text for certain
2539 * mime types, so we handle the mime-type sorting ourselves.
2541 result
= compare_by_type (file_1
, file_2
);
2543 result
= compare_by_full_path (file_1
, file_2
);
2546 case NAUTILUS_FILE_SORT_BY_MTIME
:
2547 result
= compare_by_time (file_1
, file_2
, NAUTILUS_DATE_TYPE_MODIFIED
);
2549 result
= compare_by_full_path (file_1
, file_2
);
2552 case NAUTILUS_FILE_SORT_BY_ATIME
:
2553 result
= compare_by_time (file_1
, file_2
, NAUTILUS_DATE_TYPE_ACCESSED
);
2555 result
= compare_by_full_path (file_1
, file_2
);
2558 case NAUTILUS_FILE_SORT_BY_EMBLEMS
:
2559 /* GnomeVFS doesn't know squat about our emblems, so
2560 * we handle comparing them here, before falling back
2563 result
= compare_by_emblems (file_1
, file_2
);
2565 result
= compare_by_full_path (file_1
, file_2
);
2569 g_return_val_if_reached (0);
2581 nautilus_file_compare_for_sort_by_attribute_q (NautilusFile
*file_1
,
2582 NautilusFile
*file_2
,
2584 gboolean directories_first
,
2589 if (file_1
== file_2
) {
2593 /* Convert certain attributes into NautilusFileSortTypes and use
2594 * nautilus_file_compare_for_sort()
2596 if (attribute
== 0 || attribute
== attribute_name_q
) {
2597 return nautilus_file_compare_for_sort (file_1
, file_2
,
2598 NAUTILUS_FILE_SORT_BY_DISPLAY_NAME
,
2601 } else if (attribute
== attribute_size_q
) {
2602 return nautilus_file_compare_for_sort (file_1
, file_2
,
2603 NAUTILUS_FILE_SORT_BY_SIZE
,
2606 } else if (attribute
== attribute_type_q
) {
2607 return nautilus_file_compare_for_sort (file_1
, file_2
,
2608 NAUTILUS_FILE_SORT_BY_TYPE
,
2611 } else if (attribute
== attribute_modification_date_q
|| attribute
== attribute_date_modified_q
) {
2612 return nautilus_file_compare_for_sort (file_1
, file_2
,
2613 NAUTILUS_FILE_SORT_BY_MTIME
,
2616 } else if (attribute
== attribute_accessed_date_q
|| attribute
== attribute_date_accessed_q
) {
2617 return nautilus_file_compare_for_sort (file_1
, file_2
,
2618 NAUTILUS_FILE_SORT_BY_ATIME
,
2621 } else if (attribute
== attribute_emblems_q
) {
2622 return nautilus_file_compare_for_sort (file_1
, file_2
,
2623 NAUTILUS_FILE_SORT_BY_EMBLEMS
,
2628 /* it is a normal attribute, compare by strings */
2630 result
= nautilus_file_compare_for_sort_internal (file_1
, file_2
, directories_first
);
2636 value_1
= nautilus_file_get_string_attribute_q (file_1
,
2638 value_2
= nautilus_file_get_string_attribute_q (file_2
,
2641 if (value_1
!= NULL
&& value_2
!= NULL
) {
2642 result
= strcmp (value_1
, value_2
);
2657 nautilus_file_compare_for_sort_by_attribute (NautilusFile
*file_1
,
2658 NautilusFile
*file_2
,
2659 const char *attribute
,
2660 gboolean directories_first
,
2663 return nautilus_file_compare_for_sort_by_attribute_q (file_1
, file_2
,
2664 g_quark_from_string (attribute
),
2671 * nautilus_file_compare_name:
2672 * @file: A file object
2673 * @pattern: A string we are comparing it with
2675 * Return value: result of a comparison of the file name and the given pattern,
2676 * using the same sorting order as sort by name.
2679 nautilus_file_compare_display_name (NautilusFile
*file
,
2680 const char *pattern
)
2685 g_return_val_if_fail (pattern
!= NULL
, -1);
2687 name
= nautilus_file_peek_display_name (file
);
2688 result
= g_utf8_collate (name
, pattern
);
2694 nautilus_file_is_hidden_file (NautilusFile
*file
)
2696 return file
->details
->is_hidden
;
2700 nautilus_file_is_backup_file (NautilusFile
*file
)
2702 return file
->details
->is_backup
;
2706 is_file_hidden (NautilusFile
*file
)
2708 return file
->details
->directory
->details
->hidden_file_hash
!= NULL
&&
2709 g_hash_table_lookup (file
->details
->directory
->details
->hidden_file_hash
,
2710 eel_ref_str_peek (file
->details
->name
)) != NULL
;
2715 nautilus_file_should_show (NautilusFile
*file
,
2716 gboolean show_hidden
,
2717 gboolean show_backup
)
2719 return (show_hidden
|| (!nautilus_file_is_hidden_file (file
) && !is_file_hidden (file
))) &&
2720 (show_backup
|| !nautilus_file_is_backup_file (file
));
2725 nautilus_file_is_home (NautilusFile
*file
)
2729 dir
= file
->details
->directory
->details
->location
;
2734 return nautilus_is_home_directory_file (dir
,
2735 eel_ref_str_peek (file
->details
->name
));
2739 nautilus_file_is_in_desktop (NautilusFile
*file
)
2741 if (file
->details
->directory
->details
->location
) {
2742 return nautilus_is_desktop_directory (file
->details
->directory
->details
->location
);
2749 filter_hidden_and_backup_partition_callback (gpointer data
,
2750 gpointer callback_data
)
2753 FilterOptions options
;
2755 file
= NAUTILUS_FILE (data
);
2756 options
= GPOINTER_TO_INT (callback_data
);
2758 return nautilus_file_should_show (file
,
2759 options
& SHOW_HIDDEN
,
2760 options
& SHOW_BACKUP
);
2764 nautilus_file_list_filter_hidden_and_backup (GList
*files
,
2765 gboolean show_hidden
,
2766 gboolean show_backup
)
2768 GList
*filtered_files
;
2769 GList
*removed_files
;
2771 /* FIXME bugzilla.gnome.org 40653:
2772 * Eventually this should become a generic filtering thingy.
2775 filtered_files
= nautilus_file_list_copy (files
);
2776 filtered_files
= eel_g_list_partition (filtered_files
,
2777 filter_hidden_and_backup_partition_callback
,
2778 GINT_TO_POINTER ((show_hidden
? SHOW_HIDDEN
: 0) |
2779 (show_backup
? SHOW_BACKUP
: 0)),
2781 nautilus_file_list_free (removed_files
);
2783 return filtered_files
;
2789 /* We use the file's URI for the metadata for files in a directory,
2790 * but we use a hard-coded string for the metadata for the directory
2794 get_metadata_name (NautilusFile
*file
)
2796 if (nautilus_file_is_self_owned (file
)) {
2797 return FILE_NAME_FOR_DIRECTORY_METADATA
;
2799 return eel_ref_str_peek (file
->details
->name
);
2803 nautilus_file_get_metadata (NautilusFile
*file
,
2805 const char *default_metadata
)
2807 g_return_val_if_fail (key
!= NULL
, g_strdup (default_metadata
));
2808 g_return_val_if_fail (key
[0] != '\0', g_strdup (default_metadata
));
2810 return g_strdup (default_metadata
);
2812 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), g_strdup (default_metadata
));
2814 return nautilus_directory_get_file_metadata
2815 (file
->details
->directory
,
2816 get_metadata_name (file
),
2822 nautilus_file_get_metadata_list (NautilusFile
*file
,
2823 const char *list_key
,
2824 const char *list_subkey
)
2826 g_return_val_if_fail (list_key
!= NULL
, NULL
);
2827 g_return_val_if_fail (list_key
[0] != '\0', NULL
);
2828 g_return_val_if_fail (list_subkey
!= NULL
, NULL
);
2829 g_return_val_if_fail (list_subkey
[0] != '\0', NULL
);
2833 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
2835 return nautilus_directory_get_file_metadata_list
2836 (file
->details
->directory
,
2837 get_metadata_name (file
),
2843 nautilus_file_set_metadata (NautilusFile
*file
,
2845 const char *default_metadata
,
2846 const char *metadata
)
2848 g_return_if_fail (NAUTILUS_IS_FILE (file
));
2849 g_return_if_fail (key
!= NULL
);
2850 g_return_if_fail (key
[0] != '\0');
2852 nautilus_directory_set_file_metadata
2853 (file
->details
->directory
,
2854 get_metadata_name (file
),
2861 nautilus_file_set_metadata_list (NautilusFile
*file
,
2862 const char *list_key
,
2863 const char *list_subkey
,
2866 g_return_if_fail (NAUTILUS_IS_FILE (file
));
2867 g_return_if_fail (list_key
!= NULL
);
2868 g_return_if_fail (list_key
[0] != '\0');
2869 g_return_if_fail (list_subkey
!= NULL
);
2870 g_return_if_fail (list_subkey
[0] != '\0');
2872 nautilus_directory_set_file_metadata_list
2873 (file
->details
->directory
,
2874 get_metadata_name (file
),
2882 nautilus_file_get_boolean_metadata (NautilusFile
*file
,
2884 gboolean default_metadata
)
2886 g_return_val_if_fail (key
!= NULL
, default_metadata
);
2887 g_return_val_if_fail (key
[0] != '\0', default_metadata
);
2889 return default_metadata
;
2891 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), default_metadata
);
2893 return nautilus_directory_get_boolean_file_metadata
2894 (file
->details
->directory
,
2895 get_metadata_name (file
),
2901 nautilus_file_get_integer_metadata (NautilusFile
*file
,
2903 int default_metadata
)
2905 g_return_val_if_fail (key
!= NULL
, default_metadata
);
2906 g_return_val_if_fail (key
[0] != '\0', default_metadata
);
2908 return default_metadata
;
2910 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), default_metadata
);
2912 return nautilus_directory_get_integer_file_metadata
2913 (file
->details
->directory
,
2914 get_metadata_name (file
),
2921 nautilus_file_set_boolean_metadata (NautilusFile
*file
,
2923 gboolean default_metadata
,
2926 g_return_if_fail (NAUTILUS_IS_FILE (file
));
2927 g_return_if_fail (key
!= NULL
);
2928 g_return_if_fail (key
[0] != '\0');
2930 nautilus_directory_set_boolean_file_metadata
2931 (file
->details
->directory
,
2932 get_metadata_name (file
),
2939 nautilus_file_set_integer_metadata (NautilusFile
*file
,
2941 int default_metadata
,
2944 g_return_if_fail (NAUTILUS_IS_FILE (file
));
2945 g_return_if_fail (key
!= NULL
);
2946 g_return_if_fail (key
[0] != '\0');
2948 nautilus_directory_set_integer_file_metadata
2949 (file
->details
->directory
,
2950 get_metadata_name (file
),
2957 nautilus_file_peek_display_name_collation_key (NautilusFile
*file
)
2961 res
= file
->details
->display_name_collation_key
;
2969 nautilus_file_peek_display_name (NautilusFile
*file
)
2974 /* Default to display name based on filename if its not set yet */
2976 if (file
->details
->display_name
== NULL
) {
2977 name
= eel_ref_str_peek (file
->details
->name
);
2978 if (g_utf8_validate (name
, -1, NULL
)) {
2979 nautilus_file_set_display_name (file
,
2984 escaped_name
= g_uri_escape_string (name
, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH
, TRUE
);
2985 nautilus_file_set_display_name (file
,
2989 g_free (escaped_name
);
2993 return eel_ref_str_peek (file
->details
->display_name
);
2997 nautilus_file_get_display_name (NautilusFile
*file
)
2999 return g_strdup (nautilus_file_peek_display_name (file
));
3003 nautilus_file_get_edit_name (NautilusFile
*file
)
3007 res
= eel_ref_str_peek (file
->details
->edit_name
);
3011 return g_strdup (res
);
3015 nautilus_file_get_name (NautilusFile
*file
)
3017 return g_strdup (eel_ref_str_peek (file
->details
->name
));
3021 * nautilus_file_get_description:
3022 * @file: a #NautilusFile.
3024 * Gets the standard::description key from @file, if
3025 * it has been cached.
3027 * Returns: a string containing the value of the standard::description
3031 nautilus_file_get_description (NautilusFile
*file
)
3033 return g_strdup (file
->details
->description
);
3037 nautilus_file_monitor_add (NautilusFile
*file
,
3038 gconstpointer client
,
3039 NautilusFileAttributes attributes
)
3041 g_return_if_fail (NAUTILUS_IS_FILE (file
));
3042 g_return_if_fail (client
!= NULL
);
3045 (NAUTILUS_FILE_CLASS
, file
,
3046 monitor_add
, (file
, client
, attributes
));
3050 nautilus_file_monitor_remove (NautilusFile
*file
,
3051 gconstpointer client
)
3053 g_return_if_fail (NAUTILUS_IS_FILE (file
));
3054 g_return_if_fail (client
!= NULL
);
3057 (NAUTILUS_FILE_CLASS
, file
,
3058 monitor_remove
, (file
, client
));
3062 nautilus_file_is_launcher (NautilusFile
*file
)
3064 return file
->details
->is_launcher
;
3068 nautilus_file_has_activation_uri (NautilusFile
*file
)
3070 return file
->details
->activation_location
!= NULL
;
3074 /* Return the uri associated with the passed-in file, which may not be
3075 * the actual uri if the file is an desktop file or a nautilus
3079 nautilus_file_get_activation_uri (NautilusFile
*file
)
3081 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
3083 if (file
->details
->activation_location
!= NULL
) {
3084 return g_file_get_uri (file
->details
->activation_location
);
3087 return nautilus_file_get_uri (file
);
3091 nautilus_file_get_activation_location (NautilusFile
*file
)
3093 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
3095 if (file
->details
->activation_location
!= NULL
) {
3096 return g_object_ref (file
->details
->activation_location
);
3099 return nautilus_file_get_location (file
);
3104 nautilus_file_get_drop_target_uri (NautilusFile
*file
)
3106 char *uri
, *target_uri
;
3108 NautilusDesktopLink
*link
;
3110 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
3112 if (NAUTILUS_IS_DESKTOP_ICON_FILE (file
)) {
3113 link
= nautilus_desktop_icon_file_get_link (NAUTILUS_DESKTOP_ICON_FILE (file
));
3116 location
= nautilus_desktop_link_get_activation_location (link
);
3117 g_object_unref (link
);
3118 if (location
!= NULL
) {
3119 uri
= g_file_get_uri (location
);
3120 g_object_unref (location
);
3126 uri
= nautilus_file_get_uri (file
);
3128 /* Check for Nautilus link */
3129 if (nautilus_file_is_nautilus_link (file
)) {
3130 location
= nautilus_file_get_location (file
);
3131 /* FIXME bugzilla.gnome.org 43020: This does sync. I/O and works only locally. */
3132 if (g_file_is_native (location
)) {
3133 target_uri
= nautilus_link_local_get_link_uri (uri
);
3134 if (target_uri
!= NULL
) {
3139 g_object_unref (location
);
3146 is_uri_relative (const char *uri
)
3150 scheme
= g_uri_parse_scheme (uri
);
3152 return scheme
== NULL
;
3156 get_custom_icon_metadata_uri (NautilusFile
*file
)
3158 char *custom_icon_uri
;
3162 uri
= nautilus_file_get_metadata (file
, NAUTILUS_METADATA_KEY_CUSTOM_ICON
, NULL
);
3164 nautilus_file_is_directory (file
) &&
3165 is_uri_relative (uri
)) {
3166 dir_uri
= nautilus_file_get_uri (file
);
3167 custom_icon_uri
= g_build_filename (dir_uri
, uri
, NULL
);
3171 custom_icon_uri
= uri
;
3173 return custom_icon_uri
;
3177 get_custom_icon (NautilusFile
*file
)
3179 char *custom_icon_uri
;
3189 /* Metadata takes precedence */
3190 custom_icon_uri
= get_custom_icon_metadata_uri (file
);
3192 if (custom_icon_uri
) {
3193 icon_file
= g_file_new_for_uri (custom_icon_uri
);
3194 icon
= g_file_icon_new (icon_file
);
3195 g_object_unref (icon_file
);
3198 if (icon
== NULL
&& file
->details
->got_link_info
&& file
->details
->custom_icon
!= NULL
) {
3199 if (g_path_is_absolute (file
->details
->custom_icon
)) {
3200 icon_file
= g_file_new_for_path (file
->details
->custom_icon
);
3201 icon
= g_file_icon_new (icon_file
);
3202 g_object_unref (icon_file
);
3204 icon
= g_themed_icon_new (file
->details
->custom_icon
);
3212 static int cached_thumbnail_limit
;
3213 static int cached_thumbnail_size
;
3214 static int show_image_thumbs
;
3216 GFilesystemPreviewType
3217 nautilus_file_get_filesystem_use_preview (NautilusFile
*file
)
3219 GFilesystemPreviewType use_preview
;
3220 NautilusFile
*parent
;
3222 parent
= nautilus_file_get_parent (file
);
3223 if (parent
!= NULL
) {
3224 use_preview
= parent
->details
->filesystem_use_preview
;
3225 g_object_unref (parent
);
3234 nautilus_file_should_show_thumbnail (NautilusFile
*file
)
3236 const char *mime_type
;
3237 GFilesystemPreviewType use_preview
;
3239 use_preview
= nautilus_file_get_filesystem_use_preview (file
);
3241 mime_type
= eel_ref_str_peek (file
->details
->mime_type
);
3242 if (mime_type
== NULL
) {
3243 mime_type
= "application/octet-stream";
3246 /* If the thumbnail has already been created, don't care about the size
3247 * of the original file.
3249 if (nautilus_thumbnail_is_mimetype_limited_by_size (mime_type
) &&
3250 file
->details
->thumbnail_path
== NULL
&&
3251 nautilus_file_get_size (file
) > (unsigned int)cached_thumbnail_limit
) {
3255 if (show_image_thumbs
== NAUTILUS_SPEED_TRADEOFF_ALWAYS
) {
3256 if (use_preview
== G_FILESYSTEM_PREVIEW_TYPE_NEVER
) {
3261 } else if (show_image_thumbs
== NAUTILUS_SPEED_TRADEOFF_NEVER
) {
3264 if (use_preview
== G_FILESYSTEM_PREVIEW_TYPE_NEVER
) {
3265 /* file system says to never thumbnail anything */
3267 } else if (use_preview
== G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL
) {
3268 /* file system says we should treat file as if it's local */
3271 /* only local files */
3272 return nautilus_file_is_local (file
);
3280 nautilus_file_get_gicon (NautilusFile
*file
,
3281 NautilusFileIconFlags flags
)
3283 const char * const * names
;
3294 if (file
->details
->icon
) {
3297 if (((flags
& NAUTILUS_FILE_ICON_FLAGS_EMBEDDING_TEXT
) ||
3298 (flags
& NAUTILUS_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT
) ||
3299 (flags
& NAUTILUS_FILE_ICON_FLAGS_FOR_OPEN_FOLDER
) ||
3300 ((flags
& NAUTILUS_FILE_ICON_FLAGS_IGNORE_VISITING
) == 0 &&
3301 nautilus_file_has_open_window (file
))) &&
3302 G_IS_THEMED_ICON (file
->details
->icon
)) {
3303 names
= g_themed_icon_get_names (G_THEMED_ICON (file
->details
->icon
));
3304 array
= g_ptr_array_new ();
3307 for (i
= 0; names
[i
] != NULL
; i
++) {
3310 if (strcmp (name
, "folder") == 0 &&
3311 (flags
& NAUTILUS_FILE_ICON_FLAGS_IGNORE_VISITING
) == 0 &&
3312 nautilus_file_has_open_window (file
)) {
3314 g_ptr_array_add (array
, "folder-visiting");
3316 if (strcmp (name
, "folder") == 0 &&
3317 (flags
& NAUTILUS_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT
)) {
3319 g_ptr_array_add (array
, "folder-drag-accept");
3321 if (strcmp (name
, "folder") == 0 &&
3322 (flags
& NAUTILUS_FILE_ICON_FLAGS_FOR_OPEN_FOLDER
)) {
3324 g_ptr_array_add (array
, "folder-open");
3326 if (strcmp (name
, "text-x-generic") == 0 &&
3327 (flags
& NAUTILUS_FILE_ICON_FLAGS_EMBEDDING_TEXT
)) {
3329 g_ptr_array_add (array
, "text-x-preview");
3331 g_ptr_array_add (array
, (char *)name
);
3335 icon
= g_themed_icon_new_from_names ((char **)array
->pdata
, array
->len
);
3338 g_ptr_array_free (array
, TRUE
);
3342 icon
= g_object_ref (file
->details
->icon
);
3348 return g_themed_icon_new ("text-x-generic");
3352 nautilus_file_get_icon (NautilusFile
*file
,
3354 NautilusFileIconFlags flags
)
3356 NautilusIconInfo
*icon
;
3358 GdkPixbuf
*raw_pixbuf
, *scaled_pixbuf
;
3365 gicon
= get_custom_icon (file
);
3367 icon
= nautilus_icon_info_lookup (gicon
, size
);
3368 g_object_unref (gicon
);
3372 modified_size
= size
* cached_thumbnail_size
/ NAUTILUS_ICON_SIZE_STANDARD
;
3374 if (flags
& NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS
&&
3375 nautilus_file_should_show_thumbnail (file
)) {
3376 if (file
->details
->thumbnail
) {
3377 if (file
->details
->thumbnail_size
== modified_size
) {
3378 scaled_pixbuf
= g_object_ref (file
->details
->thumbnail
);
3383 if (file
->details
->thumbnail_size
== 0) {
3384 raw_pixbuf
= g_object_ref (file
->details
->thumbnail
);
3386 raw_pixbuf
= nautilus_thumbnail_unframe_image (file
->details
->thumbnail
);
3389 w
= gdk_pixbuf_get_width (raw_pixbuf
);
3390 h
= gdk_pixbuf_get_height (raw_pixbuf
);
3392 /* These compensates for frame size which will be added on the raw image */
3393 s
= MAX (NAUTILUS_THUMBNAIL_FRAME_LEFT
+ w
+ NAUTILUS_THUMBNAIL_FRAME_RIGHT
,
3394 NAUTILUS_THUMBNAIL_FRAME_TOP
+ h
+ NAUTILUS_THUMBNAIL_FRAME_BOTTOM
);
3396 scale
= (double)modified_size
/ s
;
3398 scaled_pixbuf
= gdk_pixbuf_scale_simple (raw_pixbuf
,
3399 w
* scale
, h
* scale
,
3401 nautilus_thumbnail_frame_image (&scaled_pixbuf
);
3403 g_object_unref (raw_pixbuf
);
3405 if (modified_size
> file
->details
->thumbnail_size
) {
3406 /* Invalidate if we resize upward (and the
3407 loaded was not the original raw version, w/ size 0).
3409 if (file
->details
->thumbnail_size
!= 0 ||
3410 (modified_size
> 128 && !file
->details
->thumbnail_tried_original
)) {
3411 nautilus_file_invalidate_attributes (file
, NAUTILUS_FILE_ATTRIBUTE_THUMBNAIL
);
3413 file
->details
->thumbnail_size
= modified_size
;
3414 g_object_unref (file
->details
->thumbnail
);
3415 file
->details
->thumbnail
= g_object_ref (scaled_pixbuf
);
3419 icon
= nautilus_icon_info_new_for_pixbuf (scaled_pixbuf
);
3420 g_object_unref (scaled_pixbuf
);
3422 } else if (file
->details
->thumbnail_path
== NULL
&&
3423 file
->details
->can_read
&&
3424 !file
->details
->thumbnailing_failed
&&
3425 !file
->details
->is_thumbnailing
) {
3426 if (nautilus_can_thumbnail (file
)) {
3427 nautilus_create_thumbnail (file
);
3432 if (file
->details
->is_thumbnailing
&&
3433 flags
& NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS
)
3434 gicon
= g_themed_icon_new (ICON_NAME_THUMBNAIL_LOADING
);
3436 gicon
= nautilus_file_get_gicon (file
, flags
);
3439 icon
= nautilus_icon_info_lookup (gicon
, size
);
3440 g_object_unref (gicon
);
3444 return nautilus_icon_info_new_for_pixbuf (NULL
);
3448 nautilus_file_get_icon_pixbuf (NautilusFile
*file
,
3450 gboolean force_size
,
3451 NautilusFileIconFlags flags
)
3453 NautilusIconInfo
*info
;
3456 info
= nautilus_file_get_icon (file
, size
, flags
);
3458 pixbuf
= nautilus_icon_info_get_pixbuf_at_size (info
, size
);
3460 pixbuf
= nautilus_icon_info_get_pixbuf (info
);
3462 g_object_unref (info
);
3468 nautilus_file_get_custom_icon (NautilusFile
*file
)
3476 /* Metadata takes precedence */
3477 custom_icon
= get_custom_icon_metadata_uri (file
);
3479 if (custom_icon
== NULL
&& file
->details
->got_link_info
) {
3480 custom_icon
= g_strdup (file
->details
->custom_icon
);
3488 nautilus_file_get_date (NautilusFile
*file
,
3489 NautilusDateType date_type
,
3496 g_return_val_if_fail (date_type
== NAUTILUS_DATE_TYPE_CHANGED
3497 || date_type
== NAUTILUS_DATE_TYPE_ACCESSED
3498 || date_type
== NAUTILUS_DATE_TYPE_MODIFIED
3499 || date_type
== NAUTILUS_DATE_TYPE_PERMISSIONS_CHANGED
, FALSE
);
3505 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
3507 return EEL_CALL_METHOD_WITH_RETURN_VALUE
3508 (NAUTILUS_FILE_CLASS
, file
,
3509 get_date
, (file
, date_type
, date
));
3513 nautilus_file_get_where_string (NautilusFile
*file
)
3519 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
3521 return EEL_CALL_METHOD_WITH_RETURN_VALUE
3522 (NAUTILUS_FILE_CLASS
, file
,
3523 get_where_string
, (file
));
3526 static const char *TODAY_TIME_FORMATS
[] = {
3527 /* Today, use special word.
3528 * strftime patterns preceeded with the widest
3529 * possible resulting string for that pattern.
3531 * Note to localizers: You can look at man strftime
3532 * for details on the format, but you should only use
3533 * the specifiers from the C standard, not extensions.
3534 * These include "%" followed by one of
3535 * "aAbBcdHIjmMpSUwWxXyYZ". There are two extensions
3536 * in the Nautilus version of strftime that can be
3537 * used (and match GNU extensions). Putting a "-"
3538 * between the "%" and any numeric directive will turn
3539 * off zero padding, and putting a "_" there will use
3540 * space padding instead of zero padding.
3542 N_("today at 00:00:00 PM"),
3543 N_("today at %-I:%M:%S %p"),
3545 N_("today at 00:00 PM"),
3546 N_("today at %-I:%M %p"),
3548 N_("today, 00:00 PM"),
3549 N_("today, %-I:%M %p"),
3557 static const char *YESTERDAY_TIME_FORMATS
[] = {
3558 /* Yesterday, use special word.
3559 * Note to localizers: Same issues as "today" string.
3561 N_("yesterday at 00:00:00 PM"),
3562 N_("yesterday at %-I:%M:%S %p"),
3564 N_("yesterday at 00:00 PM"),
3565 N_("yesterday at %-I:%M %p"),
3567 N_("yesterday, 00:00 PM"),
3568 N_("yesterday, %-I:%M %p"),
3576 static const char *CURRENT_WEEK_TIME_FORMATS
[] = {
3577 /* Current week, include day of week.
3578 * Note to localizers: Same issues as "today" string.
3579 * The width measurement templates correspond to
3580 * the day/month name with the most letters.
3582 N_("Wednesday, September 00 0000 at 00:00:00 PM"),
3583 N_("%A, %B %-d %Y at %-I:%M:%S %p"),
3585 N_("Mon, Oct 00 0000 at 00:00:00 PM"),
3586 N_("%a, %b %-d %Y at %-I:%M:%S %p"),
3588 N_("Mon, Oct 00 0000 at 00:00 PM"),
3589 N_("%a, %b %-d %Y at %-I:%M %p"),
3591 N_("Oct 00 0000 at 00:00 PM"),
3592 N_("%b %-d %Y at %-I:%M %p"),
3594 N_("Oct 00 0000, 00:00 PM"),
3595 N_("%b %-d %Y, %-I:%M %p"),
3597 N_("00/00/00, 00:00 PM"),
3598 N_("%m/%-d/%y, %-I:%M %p"),
3607 nautilus_file_fit_date_as_string (NautilusFile
*file
,
3608 NautilusDateType date_type
,
3610 NautilusWidthMeasureCallback measure_callback
,
3611 NautilusTruncateCallback truncate_callback
,
3612 void *measure_context
)
3614 time_t file_time_raw
;
3615 struct tm
*file_time
;
3616 const char **formats
;
3617 const char *width_template
;
3623 guint32 file_date_age
;
3626 if (!nautilus_file_get_date (file
, date_type
, &file_time_raw
)) {
3630 file_time
= localtime (&file_time_raw
);
3632 if (date_format_pref
== NAUTILUS_DATE_FORMAT_LOCALE
) {
3633 return eel_strdup_strftime ("%c", file_time
);
3634 } else if (date_format_pref
== NAUTILUS_DATE_FORMAT_ISO
) {
3635 return eel_strdup_strftime ("%Y-%m-%d %H:%M:%S", file_time
);
3638 file_date
= eel_g_date_new_tm (file_time
);
3640 today
= g_date_new ();
3641 g_date_set_time_t (today
, time (NULL
));
3643 /* Overflow results in a large number; fine for our purposes. */
3644 file_date_age
= (g_date_get_julian (today
) -
3645 g_date_get_julian (file_date
));
3647 g_date_free (file_date
);
3648 g_date_free (today
);
3650 /* Format varies depending on how old the date is. This minimizes
3651 * the length (and thus clutter & complication) of typical dates
3652 * while providing sufficient detail for recent dates to make
3653 * them maximally understandable at a glance. Keep all format
3654 * strings separate rather than combining bits & pieces for
3655 * internationalization's sake.
3658 if (file_date_age
== 0) {
3659 formats
= TODAY_TIME_FORMATS
;
3660 } else if (file_date_age
== 1) {
3661 formats
= YESTERDAY_TIME_FORMATS
;
3662 } else if (file_date_age
< 7) {
3663 formats
= CURRENT_WEEK_TIME_FORMATS
;
3665 formats
= CURRENT_WEEK_TIME_FORMATS
;
3668 /* Find the date format that just fits the required width. Instead of measuring
3669 * the resulting string width directly, measure the width of a template that represents
3670 * the widest possible version of a date in a given format. This is done by using M, m
3671 * and 0 for the variable letters/digits respectively.
3675 for (i
= 0; ; i
+= 2) {
3676 width_template
= (formats
[i
] ? _(formats
[i
]) : NULL
);
3677 if (width_template
== NULL
) {
3678 /* no more formats left */
3679 g_assert (format
!= NULL
);
3681 /* Can't fit even the shortest format -- return an ellipsized form in the
3685 date_string
= eel_strdup_strftime (format
, file_time
);
3687 if (truncate_callback
== NULL
) {
3691 result
= (* truncate_callback
) (date_string
, width
, measure_context
);
3692 g_free (date_string
);
3696 format
= _(formats
[i
+ 1]);
3698 if (measure_callback
== NULL
) {
3699 /* don't care about fitting the width */
3703 if ((* measure_callback
) (width_template
, measure_context
) <= width
) {
3704 /* The template fits, this is the format we can fit. */
3709 return eel_strdup_strftime (format
, file_time
);
3714 * nautilus_file_fit_modified_date_as_string:
3716 * Get a user-displayable string representing a file modification date,
3717 * truncated to @width using the measuring and truncating callbacks.
3718 * @file: NautilusFile representing the file in question.
3719 * @width: The desired resulting string width.
3720 * @measure_callback: The callback used to measure the string width.
3721 * @truncate_callback: The callback used to truncate the string to a desired width.
3722 * @measure_context: Data neede when measuring and truncating.
3724 * Returns: Newly allocated string ready to display to the user.
3728 nautilus_file_fit_modified_date_as_string (NautilusFile
*file
,
3730 NautilusWidthMeasureCallback measure_callback
,
3731 NautilusTruncateCallback truncate_callback
,
3732 void *measure_context
)
3734 return nautilus_file_fit_date_as_string (file
, NAUTILUS_DATE_TYPE_MODIFIED
,
3735 width
, measure_callback
, truncate_callback
, measure_context
);
3739 * nautilus_file_get_date_as_string:
3741 * Get a user-displayable string representing a file modification date.
3742 * The caller is responsible for g_free-ing this string.
3743 * @file: NautilusFile representing the file in question.
3745 * Returns: Newly allocated string ready to display to the user.
3749 nautilus_file_get_date_as_string (NautilusFile
*file
, NautilusDateType date_type
)
3751 return nautilus_file_fit_date_as_string (file
, date_type
,
3752 0, NULL
, NULL
, NULL
);
3755 static NautilusSpeedTradeoffValue show_directory_item_count
;
3756 static NautilusSpeedTradeoffValue show_text_in_icons
;
3759 show_text_in_icons_changed_callback (gpointer callback_data
)
3761 show_text_in_icons
= eel_preferences_get_enum (NAUTILUS_PREFERENCES_SHOW_TEXT_IN_ICONS
);
3765 show_directory_item_count_changed_callback (gpointer callback_data
)
3767 show_directory_item_count
= eel_preferences_get_enum (NAUTILUS_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS
);
3771 get_speed_tradeoff_preference_for_file (NautilusFile
*file
, NautilusSpeedTradeoffValue value
)
3773 GFilesystemPreviewType use_preview
;
3775 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
3777 use_preview
= nautilus_file_get_filesystem_use_preview (file
);
3779 if (value
== NAUTILUS_SPEED_TRADEOFF_ALWAYS
) {
3780 if (use_preview
== G_FILESYSTEM_PREVIEW_TYPE_NEVER
) {
3787 if (value
== NAUTILUS_SPEED_TRADEOFF_NEVER
) {
3791 g_assert (value
== NAUTILUS_SPEED_TRADEOFF_LOCAL_ONLY
);
3793 if (use_preview
== G_FILESYSTEM_PREVIEW_TYPE_NEVER
) {
3794 /* file system says to never preview anything */
3796 } else if (use_preview
== G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL
) {
3797 /* file system says we should treat file as if it's local */
3800 /* only local files */
3801 return nautilus_file_is_local (file
);
3806 nautilus_file_should_show_directory_item_count (NautilusFile
*file
)
3808 static gboolean show_directory_item_count_callback_added
= FALSE
;
3810 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
3812 if (file
->details
->mime_type
&&
3813 strcmp (eel_ref_str_peek (file
->details
->mime_type
), "x-directory/smb-share") == 0) {
3817 /* Add the callback once for the life of our process */
3818 if (!show_directory_item_count_callback_added
) {
3819 eel_preferences_add_callback (NAUTILUS_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS
,
3820 show_directory_item_count_changed_callback
,
3822 show_directory_item_count_callback_added
= TRUE
;
3824 /* Peek for the first time */
3825 show_directory_item_count_changed_callback (NULL
);
3828 return get_speed_tradeoff_preference_for_file (file
, show_directory_item_count
);
3832 nautilus_file_should_show_type (NautilusFile
*file
)
3837 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
3839 uri
= nautilus_file_get_uri (file
);
3840 ret
= ((strcmp (uri
, "computer:///") != 0) &&
3841 (strcmp (uri
, "network:///") != 0) &&
3842 (strcmp (uri
, "smb:///") != 0));
3849 nautilus_file_should_get_top_left_text (NautilusFile
*file
)
3851 static gboolean show_text_in_icons_callback_added
= FALSE
;
3853 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
3855 /* Add the callback once for the life of our process */
3856 if (!show_text_in_icons_callback_added
) {
3857 eel_preferences_add_callback (NAUTILUS_PREFERENCES_SHOW_TEXT_IN_ICONS
,
3858 show_text_in_icons_changed_callback
,
3860 show_text_in_icons_callback_added
= TRUE
;
3862 /* Peek for the first time */
3863 show_text_in_icons_changed_callback (NULL
);
3866 if (show_text_in_icons
== NAUTILUS_SPEED_TRADEOFF_ALWAYS
) {
3870 if (show_text_in_icons
== NAUTILUS_SPEED_TRADEOFF_NEVER
) {
3874 return get_speed_tradeoff_preference_for_file (file
, show_text_in_icons
);
3878 * nautilus_file_get_directory_item_count
3880 * Get the number of items in a directory.
3881 * @file: NautilusFile representing a directory.
3882 * @count: Place to put count.
3883 * @count_unreadable: Set to TRUE (if non-NULL) if permissions prevent
3884 * the item count from being read on this directory. Otherwise set to FALSE.
3886 * Returns: TRUE if count is available.
3890 nautilus_file_get_directory_item_count (NautilusFile
*file
,
3892 gboolean
*count_unreadable
)
3894 if (count
!= NULL
) {
3897 if (count_unreadable
!= NULL
) {
3898 *count_unreadable
= FALSE
;
3901 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
3903 if (!nautilus_file_is_directory (file
)) {
3907 if (!nautilus_file_should_show_directory_item_count (file
)) {
3911 return EEL_CALL_METHOD_WITH_RETURN_VALUE
3912 (NAUTILUS_FILE_CLASS
, file
,
3913 get_item_count
, (file
, count
, count_unreadable
));
3917 * nautilus_file_get_deep_counts
3919 * Get the statistics about items inside a directory.
3920 * @file: NautilusFile representing a directory or file.
3921 * @directory_count: Place to put count of directories inside.
3922 * @files_count: Place to put count of files inside.
3923 * @unreadable_directory_count: Number of directories encountered
3924 * that were unreadable.
3925 * @total_size: Total size of all files and directories visited.
3926 * @force: Whether the deep counts should even be collected if
3927 * nautilus_file_should_show_directory_item_count returns FALSE
3930 * Returns: Status to indicate whether sizes are available.
3933 NautilusRequestStatus
3934 nautilus_file_get_deep_counts (NautilusFile
*file
,
3935 guint
*directory_count
,
3937 guint
*unreadable_directory_count
,
3938 goffset
*total_size
,
3941 if (directory_count
!= NULL
) {
3942 *directory_count
= 0;
3944 if (file_count
!= NULL
) {
3947 if (unreadable_directory_count
!= NULL
) {
3948 *unreadable_directory_count
= 0;
3950 if (total_size
!= NULL
) {
3954 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NAUTILUS_REQUEST_DONE
);
3956 if (!force
&& !nautilus_file_should_show_directory_item_count (file
)) {
3957 /* Set field so an existing value isn't treated as up-to-date
3958 * when preference changes later.
3960 file
->details
->deep_counts_status
= NAUTILUS_REQUEST_NOT_STARTED
;
3961 return file
->details
->deep_counts_status
;
3964 return EEL_CALL_METHOD_WITH_RETURN_VALUE
3965 (NAUTILUS_FILE_CLASS
, file
,
3966 get_deep_counts
, (file
,
3969 unreadable_directory_count
,
3974 nautilus_file_recompute_deep_counts (NautilusFile
*file
)
3976 if (file
->details
->deep_counts_status
!= NAUTILUS_REQUEST_IN_PROGRESS
) {
3977 file
->details
->deep_counts_status
= NAUTILUS_REQUEST_NOT_STARTED
;
3978 if (file
->details
->directory
!= NULL
) {
3979 nautilus_directory_add_file_to_work_queue (file
->details
->directory
, file
);
3980 nautilus_directory_async_state_changed (file
->details
->directory
);
3987 * nautilus_file_get_directory_item_mime_types
3989 * Get the list of mime-types present in a directory.
3990 * @file: NautilusFile representing a directory. It is an error to
3991 * call this function on a file that is not a directory.
3992 * @mime_list: Place to put the list of mime-types.
3994 * Returns: TRUE if mime-type list is available.
3998 nautilus_file_get_directory_item_mime_types (NautilusFile
*file
,
4001 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
4002 g_return_val_if_fail (mime_list
!= NULL
, FALSE
);
4004 if (!nautilus_file_is_directory (file
)
4005 || !file
->details
->got_mime_list
) {
4010 *mime_list
= eel_g_str_list_copy (file
->details
->mime_list
);
4015 nautilus_file_can_get_size (NautilusFile
*file
)
4017 return file
->details
->size
== -1;
4022 * nautilus_file_get_size
4024 * Get the file size.
4025 * @file: NautilusFile representing the file in question.
4027 * Returns: Size in bytes.
4031 nautilus_file_get_size (NautilusFile
*file
)
4033 /* Before we have info on the file, we don't know the size. */
4034 if (file
->details
->size
== -1)
4036 return file
->details
->size
;
4040 nautilus_file_get_mtime (NautilusFile
*file
)
4042 return file
->details
->mtime
;
4047 set_attributes_get_info_callback (GObject
*source_object
,
4049 gpointer callback_data
)
4051 NautilusFileOperation
*op
;
4052 GFileInfo
*new_info
;
4058 new_info
= g_file_query_info_finish (G_FILE (source_object
), res
, &error
);
4059 if (new_info
!= NULL
) {
4060 nautilus_file_update_info (op
->file
, new_info
);
4061 g_object_unref (new_info
);
4063 nautilus_file_operation_complete (op
, NULL
, error
);
4065 g_error_free (error
);
4071 set_attributes_callback (GObject
*source_object
,
4072 GAsyncResult
*result
,
4073 gpointer callback_data
)
4075 NautilusFileOperation
*op
;
4082 res
= g_file_set_attributes_finish (G_FILE (source_object
),
4088 g_file_query_info_async (G_FILE (source_object
),
4089 NAUTILUS_FILE_DEFAULT_ATTRIBUTES
,
4093 set_attributes_get_info_callback
, op
);
4095 nautilus_file_operation_complete (op
, NULL
, error
);
4096 g_error_free (error
);
4101 nautilus_file_set_attributes (NautilusFile
*file
,
4102 GFileInfo
*attributes
,
4103 NautilusFileOperationCallback callback
,
4104 gpointer callback_data
)
4106 NautilusFileOperation
*op
;
4109 op
= nautilus_file_operation_new (file
, callback
, callback_data
);
4111 location
= nautilus_file_get_location (file
);
4112 g_file_set_attributes_async (location
,
4117 set_attributes_callback
,
4119 g_object_unref (location
);
4124 * nautilus_file_can_get_permissions:
4126 * Check whether the permissions for a file are determinable.
4127 * This might not be the case for files on non-UNIX file systems.
4129 * @file: The file in question.
4131 * Return value: TRUE if the permissions are valid.
4134 nautilus_file_can_get_permissions (NautilusFile
*file
)
4136 return file
->details
->has_permissions
;
4140 * nautilus_file_can_set_permissions:
4142 * Check whether the current user is allowed to change
4143 * the permissions of a file.
4145 * @file: The file in question.
4147 * Return value: TRUE if the current user can change the
4148 * permissions of @file, FALSE otherwise. It's always possible
4149 * that when you actually try to do it, you will fail.
4152 nautilus_file_can_set_permissions (NautilusFile
*file
)
4156 if (file
->details
->uid
!= -1 &&
4157 nautilus_file_is_local (file
)) {
4158 /* Check the user. */
4159 user_id
= geteuid();
4161 /* Owner is allowed to set permissions. */
4162 if (user_id
== (uid_t
) file
->details
->uid
) {
4166 /* Root is also allowed to set permissions. */
4171 /* Nobody else is allowed. */
4175 /* pretend to have full chmod rights when no info is available, relevant when
4176 * the FS can't provide ownership info, for instance for FTP */
4181 nautilus_file_get_permissions (NautilusFile
*file
)
4183 g_return_val_if_fail (nautilus_file_can_get_permissions (file
), 0);
4185 return file
->details
->permissions
;
4189 * nautilus_file_set_permissions:
4191 * Change a file's permissions. This should only be called if
4192 * nautilus_file_can_set_permissions returned TRUE.
4194 * @file: NautilusFile representing the file in question.
4195 * @new_permissions: New permissions value. This is the whole
4196 * set of permissions, not a delta.
4199 nautilus_file_set_permissions (NautilusFile
*file
,
4200 guint32 new_permissions
,
4201 NautilusFileOperationCallback callback
,
4202 gpointer callback_data
)
4207 if (!nautilus_file_can_set_permissions (file
)) {
4208 /* Claim that something changed even if the permission change failed.
4209 * This makes it easier for some clients who see the "reverting"
4210 * to the old permissions as "changing back".
4212 nautilus_file_changed (file
);
4213 error
= g_error_new (G_IO_ERROR
, G_IO_ERROR_PERMISSION_DENIED
,
4214 _("Not allowed to set permissions"));
4215 (* callback
) (file
, NULL
, error
, callback_data
);
4216 g_error_free (error
);
4220 /* Test the permissions-haven't-changed case explicitly
4221 * because we don't want to send the file-changed signal if
4224 if (new_permissions
== file
->details
->permissions
) {
4225 (* callback
) (file
, NULL
, NULL
, callback_data
);
4229 info
= g_file_info_new ();
4230 g_file_info_set_attribute_uint32 (info
, G_FILE_ATTRIBUTE_UNIX_MODE
, new_permissions
);
4231 nautilus_file_set_attributes (file
, info
, callback
, callback_data
);
4232 g_object_unref (info
);
4236 * nautilus_file_can_get_selinux_context:
4238 * Check whether the selinux context for a file are determinable.
4239 * This might not be the case for files on non-UNIX file systems,
4240 * files without a context or systems that don't support selinux.
4242 * @file: The file in question.
4244 * Return value: TRUE if the permissions are valid.
4247 nautilus_file_can_get_selinux_context (NautilusFile
*file
)
4249 return file
->details
->selinux_context
!= NULL
;
4254 * nautilus_file_get_selinux_context:
4256 * Get a user-displayable string representing a file's selinux
4258 * @file: NautilusFile representing the file in question.
4260 * Returns: Newly allocated string ready to display to the user.
4264 nautilus_file_get_selinux_context (NautilusFile
*file
)
4269 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
4271 if (!nautilus_file_can_get_selinux_context (file
)) {
4275 raw
= file
->details
->selinux_context
;
4278 if (selinux_raw_to_trans_context (raw
, &translated
) == 0) {
4280 tmp
= g_strdup (translated
);
4281 freecon (translated
);
4287 translated
= g_strdup (raw
);
4294 get_real_name (const char *name
, const char *gecos
)
4296 char *locale_string
, *part_before_comma
, *capitalized_login_name
, *real_name
;
4298 if (gecos
== NULL
) {
4302 locale_string
= eel_str_strip_substring_and_after (gecos
, ",");
4303 if (!g_utf8_validate (locale_string
, -1, NULL
)) {
4304 part_before_comma
= g_locale_to_utf8 (locale_string
, -1, NULL
, NULL
, NULL
);
4305 g_free (locale_string
);
4307 part_before_comma
= locale_string
;
4310 if (!g_utf8_validate (name
, -1, NULL
)) {
4311 locale_string
= g_locale_to_utf8 (name
, -1, NULL
, NULL
, NULL
);
4313 locale_string
= g_strdup (name
);
4316 capitalized_login_name
= eel_str_capitalize (locale_string
);
4317 g_free (locale_string
);
4319 if (capitalized_login_name
== NULL
) {
4320 real_name
= part_before_comma
;
4322 real_name
= eel_str_replace_substring
4323 (part_before_comma
, "&", capitalized_login_name
);
4324 g_free (part_before_comma
);
4328 if (eel_str_is_empty (real_name
)
4329 || eel_strcmp (name
, real_name
) == 0
4330 || eel_strcmp (capitalized_login_name
, real_name
) == 0) {
4335 g_free (capitalized_login_name
);
4341 get_user_and_real_name_from_id (uid_t uid
)
4344 char *real_name
, *user_and_real_name
;
4346 name
= nautilus_users_cache_get_name (uid
);
4347 gecos
= nautilus_users_cache_get_gecos (uid
);
4349 real_name
= get_real_name (name
, gecos
);
4350 if (real_name
!= NULL
) {
4351 user_and_real_name
= g_strdup_printf ("%s - %s", name
, real_name
);
4353 user_and_real_name
= g_strdup (name
);
4360 return user_and_real_name
;
4364 get_group_id_from_group_name (const char *group_name
, uid_t
*gid
)
4366 struct group
*group
;
4368 g_assert (gid
!= NULL
);
4370 group
= getgrnam (group_name
);
4372 if (group
== NULL
) {
4376 *gid
= group
->gr_gid
;
4382 get_ids_from_user_name (const char *user_name
, uid_t
*uid
, uid_t
*gid
)
4384 struct passwd
*password_info
;
4386 g_assert (uid
!= NULL
|| gid
!= NULL
);
4388 password_info
= getpwnam (user_name
);
4390 if (password_info
== NULL
) {
4395 *uid
= password_info
->pw_uid
;
4399 *gid
= password_info
->pw_gid
;
4406 get_user_id_from_user_name (const char *user_name
, uid_t
*id
)
4408 return get_ids_from_user_name (user_name
, id
, NULL
);
4412 get_id_from_digit_string (const char *digit_string
, uid_t
*id
)
4417 g_assert (id
!= NULL
);
4419 /* Only accept string if it has one integer with nothing
4422 if (sscanf (digit_string
, "%ld%c", &scanned_id
, &c
) != 1) {
4430 * nautilus_file_can_get_owner:
4432 * Check whether the owner a file is determinable.
4433 * This might not be the case for files on non-UNIX file systems.
4435 * @file: The file in question.
4437 * Return value: TRUE if the owner is valid.
4440 nautilus_file_can_get_owner (NautilusFile
*file
)
4442 /* Before we have info on a file, the owner is unknown. */
4443 return file
->details
->uid
!= -1;
4447 * nautilus_file_get_owner_name:
4449 * Get the user name of the file's owner. If the owner has no
4450 * name, returns the userid as a string. The caller is responsible
4451 * for g_free-ing this string.
4453 * @file: The file in question.
4455 * Return value: A newly-allocated string.
4458 nautilus_file_get_owner_name (NautilusFile
*file
)
4460 return nautilus_file_get_owner_as_string (file
, FALSE
);
4464 * nautilus_file_can_set_owner:
4466 * Check whether the current user is allowed to change
4467 * the owner of a file.
4469 * @file: The file in question.
4471 * Return value: TRUE if the current user can change the
4472 * owner of @file, FALSE otherwise. It's always possible
4473 * that when you actually try to do it, you will fail.
4476 nautilus_file_can_set_owner (NautilusFile
*file
)
4478 /* Not allowed to set the owner if we can't
4479 * even read it. This can happen on non-UNIX file
4482 if (!nautilus_file_can_get_owner (file
)) {
4486 /* Only root is also allowed to set the owner. */
4487 return geteuid() == 0;
4491 * nautilus_file_set_owner:
4493 * Set the owner of a file. This will only have any effect if
4494 * nautilus_file_can_set_owner returns TRUE.
4496 * @file: The file in question.
4497 * @user_name_or_id: The user name to set the owner to.
4498 * If the string does not match any user name, and the
4499 * string is an integer, the owner will be set to the
4500 * userid represented by that integer.
4501 * @callback: Function called when asynch owner change succeeds or fails.
4502 * @callback_data: Parameter passed back with callback function.
4505 nautilus_file_set_owner (NautilusFile
*file
,
4506 const char *user_name_or_id
,
4507 NautilusFileOperationCallback callback
,
4508 gpointer callback_data
)
4514 if (!nautilus_file_can_set_owner (file
)) {
4515 /* Claim that something changed even if the permission
4516 * change failed. This makes it easier for some
4517 * clients who see the "reverting" to the old owner as
4520 nautilus_file_changed (file
);
4521 error
= g_error_new (G_IO_ERROR
, G_IO_ERROR_PERMISSION_DENIED
,
4522 _("Not allowed to set owner"));
4523 (* callback
) (file
, NULL
, error
, callback_data
);
4524 g_error_free (error
);
4528 /* If no match treating user_name_or_id as name, try treating
4531 if (!get_user_id_from_user_name (user_name_or_id
, &new_id
)
4532 && !get_id_from_digit_string (user_name_or_id
, &new_id
)) {
4533 /* Claim that something changed even if the permission
4534 * change failed. This makes it easier for some
4535 * clients who see the "reverting" to the old owner as
4538 nautilus_file_changed (file
);
4539 error
= g_error_new (G_IO_ERROR
, G_IO_ERROR_INVALID_ARGUMENT
,
4540 _("Specified owner '%s' doesn't exist"), user_name_or_id
);
4541 (* callback
) (file
, NULL
, error
, callback_data
);
4542 g_error_free (error
);
4546 /* Test the owner-hasn't-changed case explicitly because we
4547 * don't want to send the file-changed signal if nothing
4550 if (new_id
== (uid_t
) file
->details
->uid
) {
4551 (* callback
) (file
, NULL
, NULL
, callback_data
);
4555 info
= g_file_info_new ();
4556 g_file_info_set_attribute_uint32 (info
, G_FILE_ATTRIBUTE_UNIX_UID
, new_id
);
4557 nautilus_file_set_attributes (file
, info
, callback
, callback_data
);
4558 g_object_unref (info
);
4562 * nautilus_get_user_names:
4564 * Get a list of user names. For users with a different associated
4565 * "real name", the real name follows the standard user name, separated
4566 * by a carriage return. The caller is responsible for freeing this list
4570 nautilus_get_user_names (void)
4573 char *real_name
, *name
;
4574 struct passwd
*user
;
4580 while ((user
= getpwent ()) != NULL
) {
4581 real_name
= get_real_name (user
->pw_name
, user
->pw_gecos
);
4582 if (real_name
!= NULL
) {
4583 name
= g_strconcat (user
->pw_name
, "\n", real_name
, NULL
);
4585 name
= g_strdup (user
->pw_name
);
4588 list
= g_list_prepend (list
, name
);
4593 return eel_g_str_list_alphabetize (list
);
4597 * nautilus_file_can_get_group:
4599 * Check whether the group a file is determinable.
4600 * This might not be the case for files on non-UNIX file systems.
4602 * @file: The file in question.
4604 * Return value: TRUE if the group is valid.
4607 nautilus_file_can_get_group (NautilusFile
*file
)
4609 /* Before we have info on a file, the group is unknown. */
4610 return file
->details
->gid
!= -1;
4614 * nautilus_file_get_group_name:
4616 * Get the name of the file's group. If the group has no
4617 * name, returns the groupid as a string. The caller is responsible
4618 * for g_free-ing this string.
4620 * @file: The file in question.
4622 * Return value: A newly-allocated string.
4625 nautilus_file_get_group_name (NautilusFile
*file
)
4629 /* Before we have info on a file, the owner is unknown. */
4630 if (file
->details
->gid
== -1) {
4634 group_name
= nautilus_groups_cache_get_name ((gid_t
) file
->details
->gid
);
4635 if (group_name
== NULL
) {
4636 /* In the oddball case that the group name has been set to an id for which
4637 * there is no defined group, return the id in string form.
4639 group_name
= g_strdup_printf ("%d", file
->details
->gid
);
4646 * nautilus_file_can_set_group:
4648 * Check whether the current user is allowed to change
4649 * the group of a file.
4651 * @file: The file in question.
4653 * Return value: TRUE if the current user can change the
4654 * group of @file, FALSE otherwise. It's always possible
4655 * that when you actually try to do it, you will fail.
4658 nautilus_file_can_set_group (NautilusFile
*file
)
4662 /* Not allowed to set the permissions if we can't
4663 * even read them. This can happen on non-UNIX file
4666 if (!nautilus_file_can_get_group (file
)) {
4670 /* Check the user. */
4671 user_id
= geteuid();
4673 /* Owner is allowed to set group (with restrictions). */
4674 if (user_id
== (uid_t
) file
->details
->uid
) {
4678 /* Root is also allowed to set group. */
4683 /* Nobody else is allowed. */
4687 /* Get a list of group names, filtered to only the ones
4688 * that contain the given username. If the username is
4689 * NULL, returns a list of all group names.
4692 nautilus_get_group_names_for_user (void)
4695 struct group
*group
;
4697 gid_t gid_list
[NGROUPS_MAX
+ 1];
4702 count
= getgroups (NGROUPS_MAX
+ 1, gid_list
);
4703 for (i
= 0; i
< count
; i
++) {
4704 group
= getgrgid (gid_list
[i
]);
4708 list
= g_list_prepend (list
, g_strdup (group
->gr_name
));
4711 return eel_g_str_list_alphabetize (list
);
4715 * nautilus_get_group_names:
4717 * Get a list of all group names.
4720 nautilus_get_all_group_names (void)
4723 struct group
*group
;
4729 while ((group
= getgrent ()) != NULL
)
4730 list
= g_list_prepend (list
, g_strdup (group
->gr_name
));
4734 return eel_g_str_list_alphabetize (list
);
4738 * nautilus_file_get_settable_group_names:
4740 * Get a list of all group names that the current user
4741 * can set the group of a specific file to.
4743 * @file: The NautilusFile in question.
4746 nautilus_file_get_settable_group_names (NautilusFile
*file
)
4751 if (!nautilus_file_can_set_group (file
)) {
4755 /* Check the user. */
4756 user_id
= geteuid();
4759 /* Root is allowed to set group to anything. */
4760 result
= nautilus_get_all_group_names ();
4761 } else if (user_id
== (uid_t
) file
->details
->uid
) {
4762 /* Owner is allowed to set group to any that owner is member of. */
4763 result
= nautilus_get_group_names_for_user ();
4765 g_warning ("unhandled case in nautilus_get_settable_group_names");
4773 * nautilus_file_set_group:
4775 * Set the group of a file. This will only have any effect if
4776 * nautilus_file_can_set_group returns TRUE.
4778 * @file: The file in question.
4779 * @group_name_or_id: The group name to set the owner to.
4780 * If the string does not match any group name, and the
4781 * string is an integer, the group will be set to the
4782 * group id represented by that integer.
4783 * @callback: Function called when asynch group change succeeds or fails.
4784 * @callback_data: Parameter passed back with callback function.
4787 nautilus_file_set_group (NautilusFile
*file
,
4788 const char *group_name_or_id
,
4789 NautilusFileOperationCallback callback
,
4790 gpointer callback_data
)
4796 if (!nautilus_file_can_set_group (file
)) {
4797 /* Claim that something changed even if the group
4798 * change failed. This makes it easier for some
4799 * clients who see the "reverting" to the old group as
4802 nautilus_file_changed (file
);
4803 error
= g_error_new (G_IO_ERROR
, G_IO_ERROR_PERMISSION_DENIED
,
4804 _("Not allowed to set group"));
4805 (* callback
) (file
, NULL
, error
, callback_data
);
4806 g_error_free (error
);
4810 /* If no match treating group_name_or_id as name, try treating
4813 if (!get_group_id_from_group_name (group_name_or_id
, &new_id
)
4814 && !get_id_from_digit_string (group_name_or_id
, &new_id
)) {
4815 /* Claim that something changed even if the group
4816 * change failed. This makes it easier for some
4817 * clients who see the "reverting" to the old group as
4820 nautilus_file_changed (file
);
4821 error
= g_error_new (G_IO_ERROR
, G_IO_ERROR_INVALID_ARGUMENT
,
4822 _("Specified group '%s' doesn't exist"), group_name_or_id
);
4823 (* callback
) (file
, NULL
, error
, callback_data
);
4824 g_error_free (error
);
4828 if (new_id
== (gid_t
) file
->details
->gid
) {
4829 (* callback
) (file
, NULL
, NULL
, callback_data
);
4834 info
= g_file_info_new ();
4835 g_file_info_set_attribute_uint32 (info
, G_FILE_ATTRIBUTE_UNIX_GID
, new_id
);
4836 nautilus_file_set_attributes (file
, info
, callback
, callback_data
);
4837 g_object_unref (info
);
4841 * nautilus_file_get_octal_permissions_as_string:
4843 * Get a user-displayable string representing a file's permissions
4844 * as an octal number. The caller
4845 * is responsible for g_free-ing this string.
4846 * @file: NautilusFile representing the file in question.
4848 * Returns: Newly allocated string ready to display to the user.
4852 nautilus_file_get_octal_permissions_as_string (NautilusFile
*file
)
4854 guint32 permissions
;
4856 g_assert (NAUTILUS_IS_FILE (file
));
4858 if (!nautilus_file_can_get_permissions (file
)) {
4862 permissions
= file
->details
->permissions
;
4863 return g_strdup_printf ("%03o", permissions
);
4867 * nautilus_file_get_permissions_as_string:
4869 * Get a user-displayable string representing a file's permissions. The caller
4870 * is responsible for g_free-ing this string.
4871 * @file: NautilusFile representing the file in question.
4873 * Returns: Newly allocated string ready to display to the user.
4877 nautilus_file_get_permissions_as_string (NautilusFile
*file
)
4879 guint32 permissions
;
4880 gboolean is_directory
;
4882 gboolean suid
, sgid
, sticky
;
4884 if (!nautilus_file_can_get_permissions (file
)) {
4888 g_assert (NAUTILUS_IS_FILE (file
));
4890 permissions
= file
->details
->permissions
;
4891 is_directory
= nautilus_file_is_directory (file
);
4892 is_link
= nautilus_file_is_symbolic_link (file
);
4894 /* We use ls conventions for displaying these three obscure flags */
4895 suid
= permissions
& S_ISGID
;
4896 sgid
= permissions
& S_ISGID
;
4897 sticky
= permissions
& S_ISVTX
;
4899 return g_strdup_printf ("%c%c%c%c%c%c%c%c%c%c",
4900 is_link
? 'l' : is_directory
? 'd' : '-',
4901 permissions
& S_IRUSR
? 'r' : '-',
4902 permissions
& S_IWUSR
? 'w' : '-',
4903 permissions
& S_IXUSR
4904 ? (suid
? 's' : 'x')
4905 : (suid
? 'S' : '-'),
4906 permissions
& S_IRGRP
? 'r' : '-',
4907 permissions
& S_IWGRP
? 'w' : '-',
4908 permissions
& S_IXGRP
4909 ? (sgid
? 's' : 'x')
4910 : (sgid
? 'S' : '-'),
4911 permissions
& S_IROTH
? 'r' : '-',
4912 permissions
& S_IWOTH
? 'w' : '-',
4913 permissions
& S_IXOTH
4914 ? (sticky
? 't' : 'x')
4915 : (sticky
? 'T' : '-'));
4919 * nautilus_file_get_owner_as_string:
4921 * Get a user-displayable string representing a file's owner. The caller
4922 * is responsible for g_free-ing this string.
4923 * @file: NautilusFile representing the file in question.
4924 * @include_real_name: Whether or not to append the real name (if any)
4925 * for this user after the user name.
4927 * Returns: Newly allocated string ready to display to the user.
4931 nautilus_file_get_owner_as_string (NautilusFile
*file
, gboolean include_real_name
)
4935 /* Before we have info on a file, the owner is unknown. */
4936 if (file
->details
->uid
== -1) {
4940 if (include_real_name
) {
4941 user_name
= get_user_and_real_name_from_id (file
->details
->uid
);
4943 user_name
= nautilus_users_cache_get_name (file
->details
->uid
);
4946 if (user_name
== NULL
) {
4947 /* In the oddball case that the user name has been set to an id for which
4948 * there is no defined user, return the id in string form.
4950 user_name
= g_strdup_printf ("%d", file
->details
->uid
);
4957 format_item_count_for_display (guint item_count
,
4958 gboolean includes_directories
,
4959 gboolean includes_files
)
4961 g_assert (includes_directories
|| includes_files
);
4963 return g_strdup_printf (includes_directories
4965 ? ngettext ("%'u item", "%'u items", item_count
)
4966 : ngettext ("%'u folder", "%'u folders", item_count
))
4967 : ngettext ("%'u file", "%'u files", item_count
), item_count
);
4971 * nautilus_file_get_size_as_string:
4973 * Get a user-displayable string representing a file size. The caller
4974 * is responsible for g_free-ing this string. The string is an item
4975 * count for directories.
4976 * @file: NautilusFile representing the file in question.
4978 * Returns: Newly allocated string ready to display to the user.
4982 nautilus_file_get_size_as_string (NautilusFile
*file
)
4985 gboolean count_unreadable
;
4991 g_assert (NAUTILUS_IS_FILE (file
));
4993 if (nautilus_file_is_directory (file
)) {
4994 if (!nautilus_file_get_directory_item_count (file
, &item_count
, &count_unreadable
)) {
4997 return format_item_count_for_display (item_count
, TRUE
, TRUE
);
5000 if (file
->details
->size
== -1) {
5003 return g_format_size_for_display (file
->details
->size
);
5007 * nautilus_file_get_size_as_string_with_real_size:
5009 * Get a user-displayable string representing a file size. The caller
5010 * is responsible for g_free-ing this string. The string is an item
5011 * count for directories.
5012 * This function adds the real size in the string.
5013 * @file: NautilusFile representing the file in question.
5015 * Returns: Newly allocated string ready to display to the user.
5019 nautilus_file_get_size_as_string_with_real_size (NautilusFile
*file
)
5022 gboolean count_unreadable
;
5024 char * formated_plus_real
;
5031 g_assert (NAUTILUS_IS_FILE (file
));
5033 if (nautilus_file_is_directory (file
)) {
5034 if (!nautilus_file_get_directory_item_count (file
, &item_count
, &count_unreadable
)) {
5037 return format_item_count_for_display (item_count
, TRUE
, TRUE
);
5040 if (file
->details
->size
== -1) {
5044 formated
= g_format_size_for_display (file
->details
->size
);
5045 /* Do this in a separate stage so that we don't have to put G_GUINT64_FORMAT in the translated string */
5046 real_size
= g_strdup_printf (_("%"G_GUINT64_FORMAT
), (guint64
) file
->details
->size
);
5047 formated_plus_real
= g_strdup_printf (_("%s (%s bytes)"), formated
, real_size
);
5050 return formated_plus_real
;
5055 nautilus_file_get_deep_count_as_string_internal (NautilusFile
*file
,
5056 gboolean report_size
,
5057 gboolean report_directory_count
,
5058 gboolean report_file_count
)
5060 NautilusRequestStatus status
;
5061 guint directory_count
;
5063 guint unreadable_count
;
5067 /* Must ask for size or some kind of count, but not both. */
5068 g_assert (!report_size
|| (!report_directory_count
&& !report_file_count
));
5069 g_assert (report_size
|| report_directory_count
|| report_file_count
);
5075 g_assert (NAUTILUS_IS_FILE (file
));
5076 g_assert (nautilus_file_is_directory (file
));
5078 status
= nautilus_file_get_deep_counts
5079 (file
, &directory_count
, &file_count
, &unreadable_count
, &total_size
, FALSE
);
5081 /* Check whether any info is available. */
5082 if (status
== NAUTILUS_REQUEST_NOT_STARTED
) {
5086 total_count
= file_count
+ directory_count
;
5088 if (total_count
== 0) {
5090 case NAUTILUS_REQUEST_IN_PROGRESS
:
5091 /* Don't return confident "zero" until we're finished looking,
5092 * because of next case.
5095 case NAUTILUS_REQUEST_DONE
:
5096 /* Don't return "zero" if we there were contents but we couldn't read them. */
5097 if (unreadable_count
!= 0) {
5104 /* Note that we don't distinguish the "everything was readable" case
5105 * from the "some things but not everything was readable" case here.
5106 * Callers can distinguish them using nautilus_file_get_deep_counts
5107 * directly if desired.
5110 return g_format_size_for_display (total_size
);
5113 return format_item_count_for_display (report_directory_count
5114 ? (report_file_count
? total_count
: directory_count
)
5116 report_directory_count
, report_file_count
);
5120 * nautilus_file_get_deep_size_as_string:
5122 * Get a user-displayable string representing the size of all contained
5123 * items (only makes sense for directories). The caller
5124 * is responsible for g_free-ing this string.
5125 * @file: NautilusFile representing the file in question.
5127 * Returns: Newly allocated string ready to display to the user.
5131 nautilus_file_get_deep_size_as_string (NautilusFile
*file
)
5133 return nautilus_file_get_deep_count_as_string_internal (file
, TRUE
, FALSE
, FALSE
);
5137 * nautilus_file_get_deep_total_count_as_string:
5139 * Get a user-displayable string representing the count of all contained
5140 * items (only makes sense for directories). The caller
5141 * is responsible for g_free-ing this string.
5142 * @file: NautilusFile representing the file in question.
5144 * Returns: Newly allocated string ready to display to the user.
5148 nautilus_file_get_deep_total_count_as_string (NautilusFile
*file
)
5150 return nautilus_file_get_deep_count_as_string_internal (file
, FALSE
, TRUE
, TRUE
);
5154 * nautilus_file_get_deep_file_count_as_string:
5156 * Get a user-displayable string representing the count of all contained
5157 * items, not including directories. It only makes sense to call this
5158 * function on a directory. The caller
5159 * is responsible for g_free-ing this string.
5160 * @file: NautilusFile representing the file in question.
5162 * Returns: Newly allocated string ready to display to the user.
5166 nautilus_file_get_deep_file_count_as_string (NautilusFile
*file
)
5168 return nautilus_file_get_deep_count_as_string_internal (file
, FALSE
, FALSE
, TRUE
);
5172 * nautilus_file_get_deep_directory_count_as_string:
5174 * Get a user-displayable string representing the count of all contained
5175 * directories. It only makes sense to call this
5176 * function on a directory. The caller
5177 * is responsible for g_free-ing this string.
5178 * @file: NautilusFile representing the file in question.
5180 * Returns: Newly allocated string ready to display to the user.
5184 nautilus_file_get_deep_directory_count_as_string (NautilusFile
*file
)
5186 return nautilus_file_get_deep_count_as_string_internal (file
, FALSE
, TRUE
, FALSE
);
5190 * nautilus_file_get_string_attribute:
5192 * Get a user-displayable string from a named attribute. Use g_free to
5193 * free this string. If the value is unknown, returns NULL. You can call
5194 * nautilus_file_get_string_attribute_with_default if you want a non-NULL
5197 * @file: NautilusFile representing the file in question.
5198 * @attribute_name: The name of the desired attribute. The currently supported
5199 * set includes "name", "type", "mime_type", "size", "deep_size", "deep_directory_count",
5200 * "deep_file_count", "deep_total_count", "date_modified", "date_changed", "date_accessed",
5201 * "date_permissions", "owner", "group", "permissions", "octal_permissions", "uri", "where",
5202 * "link_target", "volume", "free_space", "selinux_context"
5204 * Returns: Newly allocated string ready to display to the user, or NULL
5205 * if the value is unknown or @attribute_name is not supported.
5209 nautilus_file_get_string_attribute_q (NautilusFile
*file
, GQuark attribute_q
)
5211 char *extension_attribute
;
5213 if (attribute_q
== attribute_name_q
) {
5214 return nautilus_file_get_display_name (file
);
5216 if (attribute_q
== attribute_type_q
) {
5217 return nautilus_file_get_type_as_string (file
);
5219 if (attribute_q
== attribute_mime_type_q
) {
5220 return nautilus_file_get_mime_type (file
);
5222 if (attribute_q
== attribute_size_q
) {
5223 return nautilus_file_get_size_as_string (file
);
5225 if (attribute_q
== attribute_size_detail_q
) {
5226 return nautilus_file_get_size_as_string_with_real_size (file
);
5228 if (attribute_q
== attribute_deep_size_q
) {
5229 return nautilus_file_get_deep_size_as_string (file
);
5231 if (attribute_q
== attribute_deep_file_count_q
) {
5232 return nautilus_file_get_deep_file_count_as_string (file
);
5234 if (attribute_q
== attribute_deep_directory_count_q
) {
5235 return nautilus_file_get_deep_directory_count_as_string (file
);
5237 if (attribute_q
== attribute_deep_total_count_q
) {
5238 return nautilus_file_get_deep_total_count_as_string (file
);
5240 if (attribute_q
== attribute_date_modified_q
) {
5241 return nautilus_file_get_date_as_string (file
,
5242 NAUTILUS_DATE_TYPE_MODIFIED
);
5244 if (attribute_q
== attribute_date_changed_q
) {
5245 return nautilus_file_get_date_as_string (file
,
5246 NAUTILUS_DATE_TYPE_CHANGED
);
5248 if (attribute_q
== attribute_date_accessed_q
) {
5249 return nautilus_file_get_date_as_string (file
,
5250 NAUTILUS_DATE_TYPE_ACCESSED
);
5252 if (attribute_q
== attribute_date_permissions_q
) {
5253 return nautilus_file_get_date_as_string (file
,
5254 NAUTILUS_DATE_TYPE_PERMISSIONS_CHANGED
);
5256 if (attribute_q
== attribute_permissions_q
) {
5257 return nautilus_file_get_permissions_as_string (file
);
5259 if (attribute_q
== attribute_selinux_context_q
) {
5260 return nautilus_file_get_selinux_context (file
);
5262 if (attribute_q
== attribute_octal_permissions_q
) {
5263 return nautilus_file_get_octal_permissions_as_string (file
);
5265 if (attribute_q
== attribute_owner_q
) {
5266 return nautilus_file_get_owner_as_string (file
, TRUE
);
5268 if (attribute_q
== attribute_group_q
) {
5269 return nautilus_file_get_group_name (file
);
5271 if (attribute_q
== attribute_uri_q
) {
5272 return nautilus_file_get_uri (file
);
5274 if (attribute_q
== attribute_where_q
) {
5275 return nautilus_file_get_where_string (file
);
5277 if (attribute_q
== attribute_link_target_q
) {
5278 return nautilus_file_get_symbolic_link_target_path (file
);
5280 if (attribute_q
== attribute_volume_q
) {
5281 return nautilus_file_get_volume_name (file
);
5283 if (attribute_q
== attribute_free_space_q
) {
5284 return nautilus_file_get_volume_free_space (file
);
5287 extension_attribute
= NULL
;
5289 if (file
->details
->pending_extension_attributes
) {
5290 extension_attribute
= g_hash_table_lookup (file
->details
->pending_extension_attributes
,
5291 GINT_TO_POINTER (attribute_q
));
5294 if (extension_attribute
== NULL
&& file
->details
->extension_attributes
) {
5295 extension_attribute
= g_hash_table_lookup (file
->details
->extension_attributes
,
5296 GINT_TO_POINTER (attribute_q
));
5299 return g_strdup (extension_attribute
);
5303 nautilus_file_get_string_attribute (NautilusFile
*file
, const char *attribute_name
)
5305 return nautilus_file_get_string_attribute_q (file
, g_quark_from_string (attribute_name
));
5310 * nautilus_file_get_string_attribute_with_default:
5312 * Get a user-displayable string from a named attribute. Use g_free to
5313 * free this string. If the value is unknown, returns a string representing
5314 * the unknown value, which varies with attribute. You can call
5315 * nautilus_file_get_string_attribute if you want NULL instead of a default
5318 * @file: NautilusFile representing the file in question.
5319 * @attribute_name: The name of the desired attribute. See the description of
5320 * nautilus_file_get_string for the set of available attributes.
5322 * Returns: Newly allocated string ready to display to the user, or a string
5323 * such as "unknown" if the value is unknown or @attribute_name is not supported.
5327 nautilus_file_get_string_attribute_with_default_q (NautilusFile
*file
, GQuark attribute_q
)
5331 gboolean count_unreadable
;
5332 NautilusRequestStatus status
;
5334 result
= nautilus_file_get_string_attribute_q (file
, attribute_q
);
5335 if (result
!= NULL
) {
5339 /* Supply default values for the ones we know about. */
5340 /* FIXME bugzilla.gnome.org 40646:
5341 * Use hash table and switch statement or function pointers for speed?
5343 if (attribute_q
== attribute_size_q
) {
5344 if (!nautilus_file_should_show_directory_item_count (file
)) {
5345 return g_strdup ("--");
5347 count_unreadable
= FALSE
;
5348 if (nautilus_file_is_directory (file
)) {
5349 nautilus_file_get_directory_item_count (file
, &item_count
, &count_unreadable
);
5351 return g_strdup (count_unreadable
? _("? items") : "...");
5353 if (attribute_q
== attribute_deep_size_q
) {
5354 status
= nautilus_file_get_deep_counts (file
, NULL
, NULL
, NULL
, NULL
, FALSE
);
5355 if (status
== NAUTILUS_REQUEST_DONE
) {
5356 /* This means no contents at all were readable */
5357 return g_strdup (_("? bytes"));
5359 return g_strdup ("...");
5361 if (attribute_q
== attribute_deep_file_count_q
5362 || attribute_q
== attribute_deep_directory_count_q
5363 || attribute_q
== attribute_deep_total_count_q
) {
5364 status
= nautilus_file_get_deep_counts (file
, NULL
, NULL
, NULL
, NULL
, FALSE
);
5365 if (status
== NAUTILUS_REQUEST_DONE
) {
5366 /* This means no contents at all were readable */
5367 return g_strdup (_("? items"));
5369 return g_strdup ("...");
5371 if (attribute_q
== attribute_type_q
) {
5372 return g_strdup (_("unknown type"));
5374 if (attribute_q
== attribute_mime_type_q
) {
5375 return g_strdup (_("unknown MIME type"));
5378 /* Fallback, use for both unknown attributes and attributes
5379 * for which we have no more appropriate default.
5381 return g_strdup (_("unknown"));
5385 nautilus_file_get_string_attribute_with_default (NautilusFile
*file
, const char *attribute_name
)
5387 return nautilus_file_get_string_attribute_with_default_q (file
, g_quark_from_string (attribute_name
));
5393 * Get a user-displayable string representing a file type. The caller
5394 * is responsible for g_free-ing this string.
5395 * @file: NautilusFile representing the file in question.
5397 * Returns: Newly allocated string ready to display to the user.
5401 get_description (NautilusFile
*file
)
5403 const char *mime_type
;
5406 g_assert (NAUTILUS_IS_FILE (file
));
5408 mime_type
= eel_ref_str_peek (file
->details
->mime_type
);
5409 if (eel_str_is_empty (mime_type
)) {
5413 if (g_content_type_is_unknown (mime_type
) &&
5414 nautilus_file_is_executable (file
)) {
5415 return g_strdup (_("program"));
5418 description
= g_content_type_get_description (mime_type
);
5419 if (!eel_str_is_empty (description
)) {
5423 return g_strdup (mime_type
);
5426 /* Takes ownership of string */
5428 update_description_for_link (NautilusFile
*file
, char *string
)
5432 if (nautilus_file_is_symbolic_link (file
)) {
5433 g_assert (!nautilus_file_is_broken_symbolic_link (file
));
5434 if (string
== NULL
) {
5435 return g_strdup (_("link"));
5437 /* Note to localizers: convert file type string for file
5438 * (e.g. "folder", "plain text") to file type for symbolic link
5439 * to that kind of file (e.g. "link to folder").
5441 res
= g_strdup_printf (_("Link to %s"), string
);
5450 nautilus_file_get_type_as_string (NautilusFile
*file
)
5456 if (nautilus_file_is_broken_symbolic_link (file
)) {
5457 return g_strdup (_("link (broken)"));
5460 return update_description_for_link (file
, get_description (file
));
5464 * nautilus_file_get_file_type
5466 * Return this file's type.
5467 * @file: NautilusFile representing the file in question.
5469 * Returns: The type.
5473 nautilus_file_get_file_type (NautilusFile
*file
)
5476 return G_FILE_TYPE_UNKNOWN
;
5479 return file
->details
->type
;
5483 * nautilus_file_get_mime_type
5485 * Return this file's default mime type.
5486 * @file: NautilusFile representing the file in question.
5488 * Returns: The mime type.
5492 nautilus_file_get_mime_type (NautilusFile
*file
)
5495 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
5496 if (file
->details
->mime_type
!= NULL
) {
5497 return g_strdup (eel_ref_str_peek (file
->details
->mime_type
));
5500 return g_strdup ("application/octet-stream");
5504 * nautilus_file_is_mime_type
5506 * Check whether a file is of a particular MIME type, or inherited
5508 * @file: NautilusFile representing the file in question.
5509 * @mime_type: The MIME-type string to test (e.g. "text/plain")
5511 * Return value: TRUE if @mime_type exactly matches the
5516 nautilus_file_is_mime_type (NautilusFile
*file
, const char *mime_type
)
5518 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
5519 g_return_val_if_fail (mime_type
!= NULL
, FALSE
);
5521 if (file
->details
->mime_type
== NULL
) {
5524 return g_content_type_is_a (eel_ref_str_peek (file
->details
->mime_type
),
5529 nautilus_file_is_launchable (NautilusFile
*file
)
5531 gboolean type_can_be_executable
;
5533 type_can_be_executable
= FALSE
;
5534 if (file
->details
->mime_type
!= NULL
) {
5535 type_can_be_executable
=
5536 g_content_type_can_be_executable (eel_ref_str_peek (file
->details
->mime_type
));
5539 return type_can_be_executable
&&
5540 nautilus_file_can_get_permissions (file
) &&
5541 nautilus_file_can_execute (file
) &&
5542 nautilus_file_is_executable (file
) &&
5543 !nautilus_file_is_directory (file
);
5548 * nautilus_file_get_emblem_icons
5550 * Return the list of names of emblems that this file should display,
5551 * in canonical order.
5552 * @file: NautilusFile representing the file in question.
5554 * Returns: A list of emblem names.
5558 nautilus_file_get_emblem_icons (NautilusFile
*file
,
5561 GList
*keywords
, *l
;
5572 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
5574 keywords
= nautilus_file_get_keywords (file
);
5575 keywords
= prepend_automatic_keywords (file
, keywords
);
5578 for (l
= keywords
; l
!= NULL
; l
= l
->next
) {
5581 #ifdef TRASH_IS_FAST_ENOUGH
5582 if (strcmp (keyword
, NAUTILUS_FILE_EMBLEM_NAME_TRASH
) == 0) {
5584 gboolean file_is_trash
;
5585 /* Leave out the trash emblem for the trash itself, since
5586 * putting a trash emblem on a trash icon is gilding the
5589 uri
= nautilus_file_get_uri (file
);
5590 file_is_trash
= strcmp (uri
, EEL_TRASH_URI
) == 0;
5592 if (file_is_trash
) {
5598 for (i
= 0; exclude
[i
] != NULL
; i
++) {
5599 if (strcmp (exclude
[i
], keyword
) == 0) {
5605 icon_name
= nautilus_icon_get_emblem_icon_by_name (keyword
);
5606 icon
= g_themed_icon_new (icon_name
);
5608 icons
= g_list_prepend (icons
, icon
);
5611 eel_g_list_free_deep (keywords
);
5617 nautilus_file_get_emblem_pixbufs (NautilusFile
*file
,
5619 gboolean force_size
,
5626 NautilusIconInfo
*icon_info
;
5628 icons
= nautilus_file_get_emblem_icons (file
, exclude
);
5631 for (l
= icons
; l
!= NULL
; l
= l
->next
) {
5634 icon_info
= nautilus_icon_info_lookup (icon
, size
);
5636 pixbuf
= nautilus_icon_info_get_pixbuf_nodefault_at_size (icon_info
, size
);
5638 pixbuf
= nautilus_icon_info_get_pixbuf_nodefault (icon_info
);
5642 pixbufs
= g_list_prepend (pixbufs
, pixbuf
);
5646 g_object_unref (icon_info
);
5647 g_object_unref (icon
);
5649 g_list_free (icons
);
5651 return g_list_reverse (pixbufs
);
5657 sort_keyword_list_and_remove_duplicates (GList
*keywords
)
5660 GList
*duplicate_link
;
5662 if (keywords
!= NULL
) {
5663 keywords
= eel_g_str_list_alphabetize (keywords
);
5666 while (p
->next
!= NULL
) {
5667 if (strcmp ((const char *) p
->data
, (const char *) p
->next
->data
) == 0) {
5668 duplicate_link
= p
->next
;
5669 keywords
= g_list_remove_link (keywords
, duplicate_link
);
5670 eel_g_list_free_deep (duplicate_link
);
5681 * nautilus_file_get_keywords
5683 * Return this file's keywords.
5684 * @file: NautilusFile representing the file in question.
5686 * Returns: A list of keywords.
5690 nautilus_file_get_keywords (NautilusFile
*file
)
5698 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
5700 /* Put all the keywords into a list. */
5701 keywords
= nautilus_file_get_metadata_list
5702 (file
, "keyword", "name");
5704 keywords
= g_list_concat (keywords
, eel_g_str_list_copy (file
->details
->extension_emblems
));
5705 keywords
= g_list_concat (keywords
, eel_g_str_list_copy (file
->details
->pending_extension_emblems
));
5707 return sort_keyword_list_and_remove_duplicates (keywords
);
5711 * nautilus_file_set_keywords
5713 * Change this file's keywords.
5714 * @file: NautilusFile representing the file in question.
5715 * @keywords: New set of keywords (a GList of strings).
5719 nautilus_file_set_keywords (NautilusFile
*file
, GList
*keywords
)
5721 GList
*canonical_keywords
;
5723 /* Invalidate the emblem compare cache */
5724 g_free (file
->details
->compare_by_emblem_cache
);
5725 file
->details
->compare_by_emblem_cache
= NULL
;
5727 g_return_if_fail (NAUTILUS_IS_FILE (file
));
5729 canonical_keywords
= sort_keyword_list_and_remove_duplicates
5730 (g_list_copy (keywords
));
5731 nautilus_file_set_metadata_list
5732 (file
, "keyword", "name", canonical_keywords
);
5733 g_list_free (canonical_keywords
);
5737 * nautilus_file_is_symbolic_link
5739 * Check if this file is a symbolic link.
5740 * @file: NautilusFile representing the file in question.
5742 * Returns: True if the file is a symbolic link.
5746 nautilus_file_is_symbolic_link (NautilusFile
*file
)
5748 return file
->details
->is_symlink
;
5752 nautilus_file_is_mountpoint (NautilusFile
*file
)
5754 return file
->details
->is_mountpoint
;
5758 nautilus_file_get_mount (NautilusFile
*file
)
5760 if (file
->details
->mount
) {
5761 return g_object_ref (file
->details
->mount
);
5767 * nautilus_file_is_broken_symbolic_link
5769 * Check if this file is a symbolic link with a missing target.
5770 * @file: NautilusFile representing the file in question.
5772 * Returns: True if the file is a symbolic link with a missing target.
5776 nautilus_file_is_broken_symbolic_link (NautilusFile
*file
)
5782 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
5784 /* Non-broken symbolic links return the target's type for get_file_type. */
5785 return nautilus_file_get_file_type (file
) == G_FILE_TYPE_SYMBOLIC_LINK
;
5789 * nautilus_file_get_volume_free_space
5790 * Get a nicely formatted char with free space on the file's volume
5791 * @file: NautilusFile representing the file in question.
5793 * Returns: newly-allocated copy of file size in a formatted string
5796 nautilus_file_get_volume_free_space (NautilusFile
*file
)
5805 location
= nautilus_file_get_location (file
);
5806 info
= g_file_query_filesystem_info (location
, G_FILE_ATTRIBUTE_FILESYSTEM_FREE
, NULL
, NULL
);
5808 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_FILESYSTEM_FREE
)) {
5809 free_space
= g_file_info_get_attribute_uint64 (info
, G_FILE_ATTRIBUTE_FILESYSTEM_FREE
);
5810 res
= g_format_size_for_display (free_space
);
5812 g_object_unref (info
);
5814 g_object_unref (location
);
5820 * nautilus_file_get_volume_name
5821 * Get the path of the volume the file resides on
5822 * @file: NautilusFile representing the file in question.
5824 * Returns: newly-allocated copy of the volume name of the target file,
5825 * if the volume name isn't set, it returns the mount path of the volume
5828 nautilus_file_get_volume_name (NautilusFile
*file
)
5836 location
= nautilus_file_get_location (file
);
5837 mount
= g_file_find_enclosing_mount (location
, NULL
, NULL
);
5839 res
= g_strdup (g_mount_get_name (mount
));
5840 g_object_unref (mount
);
5842 g_object_unref (location
);
5848 * nautilus_file_get_symbolic_link_target_path
5850 * Get the file path of the target of a symbolic link. It is an error
5851 * to call this function on a file that isn't a symbolic link.
5852 * @file: NautilusFile representing the symbolic link in question.
5854 * Returns: newly-allocated copy of the file path of the target of the symbolic link.
5857 nautilus_file_get_symbolic_link_target_path (NautilusFile
*file
)
5859 g_return_val_if_fail (nautilus_file_is_symbolic_link (file
), NULL
);
5861 return g_strdup (file
->details
->symlink_name
);
5865 * nautilus_file_get_symbolic_link_target_uri
5867 * Get the uri of the target of a symbolic link. It is an error
5868 * to call this function on a file that isn't a symbolic link.
5869 * @file: NautilusFile representing the symbolic link in question.
5871 * Returns: newly-allocated copy of the uri of the target of the symbolic link.
5874 nautilus_file_get_symbolic_link_target_uri (NautilusFile
*file
)
5876 GFile
*location
, *parent
, *target
;
5879 g_return_val_if_fail (nautilus_file_is_symbolic_link (file
), NULL
);
5881 if (file
->details
->symlink_name
== NULL
) {
5886 location
= nautilus_file_get_location (file
);
5887 parent
= g_file_get_parent (location
);
5888 g_object_unref (location
);
5890 target
= g_file_resolve_relative_path (parent
, file
->details
->symlink_name
);
5891 g_object_unref (parent
);
5896 target_uri
= g_file_get_uri (target
);
5897 g_object_unref (target
);
5904 * nautilus_file_is_nautilus_link
5906 * Check if this file is a "nautilus link", meaning a historical
5907 * nautilus xml link file or a desktop file.
5908 * @file: NautilusFile representing the file in question.
5910 * Returns: True if the file is a nautilus link.
5914 nautilus_file_is_nautilus_link (NautilusFile
*file
)
5916 /* NOTE: I removed the historical link here, because i don't think we
5917 even detect that mimetype anymore */
5918 return nautilus_file_is_mime_type (file
, "application/x-desktop");
5922 * nautilus_file_is_directory
5924 * Check if this file is a directory.
5925 * @file: NautilusFile representing the file in question.
5927 * Returns: TRUE if @file is a directory.
5931 nautilus_file_is_directory (NautilusFile
*file
)
5933 return nautilus_file_get_file_type (file
) == G_FILE_TYPE_DIRECTORY
;
5937 * nautilus_file_is_in_trash
5939 * Check if this file is a file in trash.
5940 * @file: NautilusFile representing the file in question.
5942 * Returns: TRUE if @file is in a trash.
5946 nautilus_file_is_in_trash (NautilusFile
*file
)
5948 g_assert (NAUTILUS_IS_FILE (file
));
5950 return nautilus_directory_is_in_trash (file
->details
->directory
);
5954 nautilus_file_get_file_info_error (NautilusFile
*file
)
5956 if (!file
->details
->get_info_failed
) {
5960 return file
->details
->get_info_error
;
5964 * nautilus_file_contains_text
5966 * Check if this file contains text.
5967 * This is private and is used to decide whether or not to read the top left text.
5968 * @file: NautilusFile representing the file in question.
5970 * Returns: TRUE if @file has a text MIME type.
5974 nautilus_file_contains_text (NautilusFile
*file
)
5980 /* All text files inherit from text/plain */
5981 return nautilus_file_is_mime_type (file
, "text/plain");
5985 * nautilus_file_is_executable
5987 * Check if this file is executable at all.
5988 * @file: NautilusFile representing the file in question.
5990 * Returns: TRUE if any of the execute bits are set. FALSE if
5991 * not, or if the permissions are unknown.
5995 nautilus_file_is_executable (NautilusFile
*file
)
5997 if (!file
->details
->has_permissions
) {
5998 /* File's permissions field is not valid.
5999 * Can't access specific permissions, so return FALSE.
6004 return file
->details
->can_execute
;
6008 * nautilus_file_peek_top_left_text
6010 * Peek at the text from the top left of the file.
6011 * @file: NautilusFile representing the file in question.
6013 * Returns: NULL if there is no text readable, otherwise, the text.
6014 * This string is owned by the file object and should not
6015 * be kept around or freed.
6019 nautilus_file_peek_top_left_text (NautilusFile
*file
,
6020 gboolean need_large_text
,
6021 gboolean
*needs_loading
)
6023 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
6025 if (!nautilus_file_should_get_top_left_text (file
)) {
6026 if (needs_loading
) {
6027 *needs_loading
= FALSE
;
6032 if (needs_loading
) {
6033 *needs_loading
= !file
->details
->top_left_text_is_up_to_date
;
6034 if (need_large_text
) {
6035 *needs_loading
|= file
->details
->got_top_left_text
!= file
->details
->got_large_top_left_text
;
6039 /* Show " ..." in the file until we read the contents in. */
6040 if (!file
->details
->got_top_left_text
) {
6042 if (nautilus_file_contains_text (file
)) {
6048 /* Show what we read in. */
6049 return file
->details
->top_left_text
;
6053 * nautilus_file_get_top_left_text
6055 * Get the text from the top left of the file.
6056 * @file: NautilusFile representing the file in question.
6058 * Returns: NULL if there is no text readable, otherwise, the text.
6062 nautilus_file_get_top_left_text (NautilusFile
*file
)
6064 return g_strdup (nautilus_file_peek_top_left_text (file
, FALSE
, NULL
));
6069 nautilus_file_mark_gone (NautilusFile
*file
)
6071 NautilusDirectory
*directory
;
6073 if (file
->details
->is_gone
)
6076 file
->details
->is_gone
= TRUE
;
6078 update_links_if_target (file
);
6080 /* Drop it from the symlink hash ! */
6081 remove_from_link_hash_table (file
);
6083 /* Let the directory know it's gone. */
6084 directory
= file
->details
->directory
;
6085 if (!nautilus_file_is_self_owned (file
)) {
6086 nautilus_directory_remove_file (directory
, file
);
6089 nautilus_file_clear_info (file
);
6091 /* FIXME bugzilla.gnome.org 42429:
6092 * Maybe we can get rid of the name too eventually, but
6093 * for now that would probably require too many if statements
6094 * everywhere anyone deals with the name. Maybe we can give it
6095 * a hard-coded "<deleted>" name or something.
6100 * nautilus_file_changed
6102 * Notify the user that this file has changed.
6103 * @file: NautilusFile representing the file in question.
6106 nautilus_file_changed (NautilusFile
*file
)
6110 g_return_if_fail (NAUTILUS_IS_FILE (file
));
6112 if (nautilus_file_is_self_owned (file
)) {
6113 nautilus_file_emit_changed (file
);
6115 fake_list
.data
= file
;
6116 fake_list
.next
= NULL
;
6117 fake_list
.prev
= NULL
;
6118 nautilus_directory_emit_change_signals
6119 (file
->details
->directory
, &fake_list
);
6124 * nautilus_file_updated_deep_count_in_progress
6126 * Notify clients that a newer deep count is available for
6127 * the directory in question.
6130 nautilus_file_updated_deep_count_in_progress (NautilusFile
*file
) {
6131 GList
*link_files
, *node
;
6133 g_assert (NAUTILUS_IS_FILE (file
));
6134 g_assert (nautilus_file_is_directory (file
));
6136 /* Send out a signal. */
6137 g_signal_emit (file
, signals
[UPDATED_DEEP_COUNT_IN_PROGRESS
], 0, file
);
6139 /* Tell link files pointing to this object about the change. */
6140 link_files
= get_link_files (file
);
6141 for (node
= link_files
; node
!= NULL
; node
= node
->next
) {
6142 nautilus_file_updated_deep_count_in_progress (NAUTILUS_FILE (node
->data
));
6144 nautilus_file_list_free (link_files
);
6148 * nautilus_file_emit_changed
6150 * Emit a file changed signal.
6151 * This can only be called by the directory, since the directory
6152 * also has to emit a files_changed signal.
6154 * @file: NautilusFile representing the file in question.
6157 nautilus_file_emit_changed (NautilusFile
*file
)
6159 GList
*link_files
, *p
;
6161 g_assert (NAUTILUS_IS_FILE (file
));
6164 /* Invalidate the emblem compare cache. -- This is not the cleanest
6165 * place to do it but it is the one guaranteed bottleneck through
6166 * which all change notifications pass.
6168 g_free (file
->details
->compare_by_emblem_cache
);
6169 file
->details
->compare_by_emblem_cache
= NULL
;
6171 /* Send out a signal. */
6172 g_signal_emit (file
, signals
[CHANGED
], 0, file
);
6174 /* Tell link files pointing to this object about the change. */
6175 link_files
= get_link_files (file
);
6176 for (p
= link_files
; p
!= NULL
; p
= p
->next
) {
6177 if (p
->data
!= file
) {
6178 nautilus_file_changed (NAUTILUS_FILE (p
->data
));
6181 nautilus_file_list_free (link_files
);
6185 * nautilus_file_is_gone
6187 * Check if a file has already been deleted.
6188 * @file: NautilusFile representing the file in question.
6190 * Returns: TRUE if the file is already gone.
6193 nautilus_file_is_gone (NautilusFile
*file
)
6195 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
6197 return file
->details
->is_gone
;
6201 * nautilus_file_is_not_yet_confirmed
6203 * Check if we're in a state where we don't know if a file really
6204 * exists or not, before the initial I/O is complete.
6205 * @file: NautilusFile representing the file in question.
6207 * Returns: TRUE if the file is already gone.
6210 nautilus_file_is_not_yet_confirmed (NautilusFile
*file
)
6212 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
6214 return !file
->details
->got_file_info
;
6218 * nautilus_file_check_if_ready
6220 * Check whether the values for a set of file attributes are
6221 * currently available, without doing any additional work. This
6222 * is useful for callers that want to reflect updated information
6223 * when it is ready but don't want to force the work required to
6224 * obtain the information, which might be slow network calls, e.g.
6226 * @file: The file being queried.
6227 * @file_attributes: A bit-mask with the desired information.
6229 * Return value: TRUE if all of the specified attributes are currently readable.
6232 nautilus_file_check_if_ready (NautilusFile
*file
,
6233 NautilusFileAttributes file_attributes
)
6235 /* To be parallel with call_when_ready, return
6236 * TRUE for NULL file.
6242 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
6244 return EEL_CALL_METHOD_WITH_RETURN_VALUE
6245 (NAUTILUS_FILE_CLASS
, file
,
6246 check_if_ready
, (file
, file_attributes
));
6250 nautilus_file_call_when_ready (NautilusFile
*file
,
6251 NautilusFileAttributes file_attributes
,
6252 NautilusFileCallback callback
,
6253 gpointer callback_data
)
6257 (* callback
) (file
, callback_data
);
6261 g_return_if_fail (NAUTILUS_IS_FILE (file
));
6264 (NAUTILUS_FILE_CLASS
, file
,
6265 call_when_ready
, (file
, file_attributes
,
6266 callback
, callback_data
));
6270 nautilus_file_cancel_call_when_ready (NautilusFile
*file
,
6271 NautilusFileCallback callback
,
6272 gpointer callback_data
)
6274 g_return_if_fail (callback
!= NULL
);
6280 g_return_if_fail (NAUTILUS_IS_FILE (file
));
6283 (NAUTILUS_FILE_CLASS
, file
,
6284 cancel_call_when_ready
, (file
, callback
, callback_data
));
6288 invalidate_directory_count (NautilusFile
*file
)
6290 file
->details
->directory_count_is_up_to_date
= FALSE
;
6294 invalidate_deep_counts (NautilusFile
*file
)
6296 file
->details
->deep_counts_status
= NAUTILUS_REQUEST_NOT_STARTED
;
6300 invalidate_mime_list (NautilusFile
*file
)
6302 file
->details
->mime_list_is_up_to_date
= FALSE
;
6306 invalidate_top_left_text (NautilusFile
*file
)
6308 file
->details
->top_left_text_is_up_to_date
= FALSE
;
6312 invalidate_file_info (NautilusFile
*file
)
6314 file
->details
->file_info_is_up_to_date
= FALSE
;
6318 invalidate_link_info (NautilusFile
*file
)
6320 file
->details
->link_info_is_up_to_date
= FALSE
;
6324 invalidate_thumbnail (NautilusFile
*file
)
6326 file
->details
->thumbnail_is_up_to_date
= FALSE
;
6330 nautilus_file_invalidate_extension_info_internal (NautilusFile
*file
)
6332 file
->details
->pending_info_providers
=
6333 nautilus_module_get_extensions_for_type (NAUTILUS_TYPE_INFO_PROVIDER
);
6337 nautilus_file_invalidate_attributes_internal (NautilusFile
*file
,
6338 NautilusFileAttributes file_attributes
)
6346 if (NAUTILUS_IS_DESKTOP_ICON_FILE (file
)) {
6347 /* Desktop icon files are always up to date.
6348 * If we invalidate their attributes they
6349 * will lose data, so we just ignore them.
6354 nautilus_directory_set_up_request (&request
, file_attributes
);
6356 if (request
.directory_count
) {
6357 invalidate_directory_count (file
);
6359 if (request
.deep_count
) {
6360 invalidate_deep_counts (file
);
6362 if (request
.mime_list
) {
6363 invalidate_mime_list (file
);
6365 if (request
.file_info
) {
6366 invalidate_file_info (file
);
6368 if (request
.top_left_text
) {
6369 invalidate_top_left_text (file
);
6371 if (request
.link_info
) {
6372 invalidate_link_info (file
);
6374 if (request
.extension_info
) {
6375 nautilus_file_invalidate_extension_info_internal (file
);
6377 if (request
.thumbnail
) {
6378 invalidate_thumbnail (file
);
6381 /* FIXME bugzilla.gnome.org 45075: implement invalidating metadata */
6385 nautilus_file_has_open_window (NautilusFile
*file
)
6387 return file
->details
->has_open_window
;
6391 nautilus_file_set_has_open_window (NautilusFile
*file
,
6392 gboolean has_open_window
)
6394 has_open_window
= (has_open_window
!= FALSE
);
6396 if (file
->details
->has_open_window
!= has_open_window
) {
6397 file
->details
->has_open_window
= has_open_window
;
6398 nautilus_file_changed (file
);
6404 nautilus_file_is_thumbnailing (NautilusFile
*file
)
6406 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
6408 return file
->details
->is_thumbnailing
;
6412 nautilus_file_set_is_thumbnailing (NautilusFile
*file
,
6413 gboolean is_thumbnailing
)
6415 g_return_if_fail (NAUTILUS_IS_FILE (file
));
6417 file
->details
->is_thumbnailing
= is_thumbnailing
;
6422 * nautilus_file_invalidate_attributes
6424 * Invalidate the specified attributes and force a reload.
6425 * @file: NautilusFile representing the file in question.
6426 * @file_attributes: attributes to froget.
6430 nautilus_file_invalidate_attributes (NautilusFile
*file
,
6431 NautilusFileAttributes file_attributes
)
6433 /* Cancel possible in-progress loads of any of these attributes */
6434 nautilus_directory_cancel_loading_file_attributes (file
->details
->directory
,
6438 /* Actually invalidate the values */
6439 nautilus_file_invalidate_attributes_internal (file
, file_attributes
);
6441 nautilus_directory_add_file_to_work_queue (file
->details
->directory
, file
);
6443 /* Kick off I/O if necessary */
6444 nautilus_directory_async_state_changed (file
->details
->directory
);
6447 NautilusFileAttributes
6448 nautilus_file_get_all_attributes (void)
6450 return NAUTILUS_FILE_ATTRIBUTE_INFO
|
6451 NAUTILUS_FILE_ATTRIBUTE_LINK_INFO
|
6452 NAUTILUS_FILE_ATTRIBUTE_DEEP_COUNTS
|
6453 NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT
|
6454 NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_MIME_TYPES
|
6455 NAUTILUS_FILE_ATTRIBUTE_METADATA
|
6456 NAUTILUS_FILE_ATTRIBUTE_TOP_LEFT_TEXT
|
6457 NAUTILUS_FILE_ATTRIBUTE_LARGE_TOP_LEFT_TEXT
|
6458 NAUTILUS_FILE_ATTRIBUTE_EXTENSION_INFO
|
6459 NAUTILUS_FILE_ATTRIBUTE_THUMBNAIL
|
6460 NAUTILUS_FILE_ATTRIBUTE_MOUNT
;
6464 nautilus_file_invalidate_all_attributes (NautilusFile
*file
)
6466 NautilusFileAttributes all_attributes
;
6468 all_attributes
= nautilus_file_get_all_attributes ();
6469 nautilus_file_invalidate_attributes (file
, all_attributes
);
6474 * nautilus_file_dump
6476 * Debugging call, prints out the contents of the file
6479 * @file: file to dump.
6482 nautilus_file_dump (NautilusFile
*file
)
6484 long size
= file
->details
->deep_size
;
6486 const char *file_kind
;
6488 uri
= nautilus_file_get_uri (file
);
6489 g_print ("uri: %s \n", uri
);
6490 if (!file
->details
->got_file_info
) {
6491 g_print ("no file info \n");
6492 } else if (file
->details
->get_info_failed
) {
6493 g_print ("failed to get file info \n");
6495 g_print ("size: %ld \n", size
);
6496 switch (file
->details
->type
) {
6497 case G_FILE_TYPE_REGULAR
:
6498 file_kind
= "regular file";
6500 case G_FILE_TYPE_DIRECTORY
:
6501 file_kind
= "folder";
6503 case G_FILE_TYPE_SPECIAL
:
6504 file_kind
= "special";
6506 case G_FILE_TYPE_SYMBOLIC_LINK
:
6507 file_kind
= "symbolic link";
6509 case G_FILE_TYPE_UNKNOWN
:
6511 file_kind
= "unknown";
6514 g_print ("kind: %s \n", file_kind
);
6515 if (file
->details
->type
== G_FILE_TYPE_SYMBOLIC_LINK
) {
6516 g_print ("link to %s \n", file
->details
->symlink_name
);
6517 /* FIXME bugzilla.gnome.org 42430: add following of symlinks here */
6519 /* FIXME bugzilla.gnome.org 42431: add permissions and other useful stuff here */
6525 * nautilus_file_list_ref
6527 * Ref all the files in a list.
6528 * @list: GList of files.
6531 nautilus_file_list_ref (GList
*list
)
6533 g_list_foreach (list
, (GFunc
) nautilus_file_ref
, NULL
);
6538 * nautilus_file_list_unref
6540 * Unref all the files in a list.
6541 * @list: GList of files.
6544 nautilus_file_list_unref (GList
*list
)
6546 g_list_foreach (list
, (GFunc
) nautilus_file_unref
, NULL
);
6550 * nautilus_file_list_free
6552 * Free a list of files after unrefing them.
6553 * @list: GList of files.
6556 nautilus_file_list_free (GList
*list
)
6558 nautilus_file_list_unref (list
);
6563 * nautilus_file_list_copy
6565 * Copy the list of files, making a new ref of each,
6566 * @list: GList of files.
6569 nautilus_file_list_copy (GList
*list
)
6571 return g_list_copy (nautilus_file_list_ref (list
));
6575 compare_by_display_name_cover (gconstpointer a
, gconstpointer b
)
6577 return compare_by_display_name (NAUTILUS_FILE (a
), NAUTILUS_FILE (b
));
6581 * nautilus_file_list_sort_by_display_name
6583 * Sort the list of files by file name.
6584 * @list: GList of files.
6587 nautilus_file_list_sort_by_display_name (GList
*list
)
6589 return g_list_sort (list
, compare_by_display_name_cover
);
6592 static GList
*ready_data_list
= NULL
;
6597 GList
*remaining_files
;
6598 NautilusFileListCallback callback
;
6599 gpointer callback_data
;
6600 } FileListReadyData
;
6603 file_list_ready_data_free (FileListReadyData
*data
)
6607 l
= g_list_find (ready_data_list
, data
);
6609 ready_data_list
= g_list_delete_link (ready_data_list
, l
);
6611 nautilus_file_list_free (data
->file_list
);
6612 g_list_free (data
->remaining_files
);
6617 static FileListReadyData
*
6618 file_list_ready_data_new (GList
*file_list
,
6619 NautilusFileListCallback callback
,
6620 gpointer callback_data
)
6622 FileListReadyData
*data
;
6624 data
= g_new0 (FileListReadyData
, 1);
6625 data
->file_list
= nautilus_file_list_copy (file_list
);
6626 data
->remaining_files
= g_list_copy (file_list
);
6627 data
->callback
= callback
;
6628 data
->callback_data
= callback_data
;
6630 ready_data_list
= g_list_prepend (ready_data_list
, data
);
6636 file_list_file_ready_callback (NautilusFile
*file
,
6639 FileListReadyData
*data
;
6642 data
->remaining_files
= g_list_remove (data
->remaining_files
, file
);
6644 if (data
->remaining_files
== NULL
) {
6645 if (data
->callback
) {
6646 (*data
->callback
) (data
->file_list
, data
->callback_data
);
6649 file_list_ready_data_free (data
);
6654 nautilus_file_list_call_when_ready (GList
*file_list
,
6655 NautilusFileAttributes attributes
,
6656 NautilusFileListHandle
**handle
,
6657 NautilusFileListCallback callback
,
6658 gpointer callback_data
)
6661 FileListReadyData
*data
;
6664 g_return_if_fail (file_list
!= NULL
);
6666 data
= file_list_ready_data_new
6667 (file_list
, callback
, callback_data
);
6670 *handle
= (NautilusFileListHandle
*) data
;
6676 file
= NAUTILUS_FILE (l
->data
);
6677 /* Need to do this here, as the list can be modified by this call */
6679 nautilus_file_call_when_ready (file
,
6681 file_list_file_ready_callback
,
6687 nautilus_file_list_cancel_call_when_ready (NautilusFileListHandle
*handle
)
6691 FileListReadyData
*data
;
6693 g_return_if_fail (handle
!= NULL
);
6695 data
= (FileListReadyData
*) handle
;
6697 l
= g_list_find (ready_data_list
, data
);
6699 for (l
= data
->remaining_files
; l
!= NULL
; l
= l
->next
) {
6700 file
= NAUTILUS_FILE (l
->data
);
6703 (NAUTILUS_FILE_CLASS
, file
,
6704 cancel_call_when_ready
, (file
, file_list_file_ready_callback
, data
));
6707 file_list_ready_data_free (data
);
6712 try_to_make_utf8 (const char *text
, int *length
)
6714 static const char *encodings_to_try
[2];
6715 static int n_encodings_to_try
= 0;
6716 gsize converted_length
;
6717 GError
*conversion_error
;
6721 if (n_encodings_to_try
== 0) {
6722 const char *charset
;
6723 gboolean charset_is_utf8
;
6725 charset_is_utf8
= g_get_charset (&charset
);
6726 if (!charset_is_utf8
) {
6727 encodings_to_try
[n_encodings_to_try
++] = charset
;
6730 if (g_ascii_strcasecmp (charset
, "ISO-8859-1") != 0) {
6731 encodings_to_try
[n_encodings_to_try
++] = "ISO-8859-1";
6736 for (i
= 0; i
< n_encodings_to_try
; i
++) {
6737 conversion_error
= NULL
;
6738 utf8_text
= g_convert (text
, *length
,
6739 "UTF-8", encodings_to_try
[i
],
6740 NULL
, &converted_length
, &conversion_error
);
6741 if (utf8_text
!= NULL
) {
6742 *length
= converted_length
;
6745 g_error_free (conversion_error
);
6753 /* Extract the top left part of the read-in text. */
6755 nautilus_extract_top_left_text (const char *text
,
6765 const char *utf8_end
;
6767 int max_bytes
, max_lines
, max_cols
;
6770 max_bytes
= NAUTILUS_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_BYTES
;
6771 max_lines
= NAUTILUS_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_LINES
;
6772 max_cols
= NAUTILUS_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE
;
6774 max_bytes
= NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_BYTES
;
6775 max_lines
= NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_LINES
;
6776 max_cols
= NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE
;
6783 /* Might be a partial utf8 character at the end if we didn't read whole file */
6784 validated
= g_utf8_validate (text
, length
, &utf8_end
);
6786 !(length
>= max_bytes
&&
6787 text
+ length
- utf8_end
< 6)) {
6788 text_copy
= try_to_make_utf8 (text
, &length
);
6790 } else if (!validated
) {
6791 length
= utf8_end
- text
;
6795 if (text
== NULL
|| length
== 0) {
6799 buffer
= g_string_new ("");
6800 end
= text
+ length
; in
= text
;
6802 for (line
= 0; line
< max_lines
; line
++) {
6803 /* Extract one line. */
6804 for (i
= 0; i
< max_cols
; ) {
6809 c
= g_utf8_get_char (in
);
6811 if (g_unichar_isprint (c
)) {
6812 g_string_append_unichar (buffer
, c
);
6816 in
= g_utf8_next_char (in
);
6822 /* Skip the rest of the line. */
6823 while (*in
!= '\n') {
6832 /* Put a new-line separator in. */
6833 g_string_append_c(buffer
, '\n');
6838 return g_string_free(buffer
, FALSE
);
6842 thumbnail_limit_changed_callback (gpointer user_data
)
6844 cached_thumbnail_limit
= eel_preferences_get_integer (NAUTILUS_PREFERENCES_IMAGE_FILE_THUMBNAIL_LIMIT
);
6846 /* Tell the world that icons might have changed. We could invent a narrower-scope
6847 * signal to mean only "thumbnails might have changed" if this ends up being slow
6850 emit_change_signals_for_all_files_in_all_directories ();
6854 thumbnail_size_changed_callback (gpointer user_data
)
6856 cached_thumbnail_size
= eel_preferences_get_integer (NAUTILUS_PREFERENCES_ICON_VIEW_THUMBNAIL_SIZE
);
6858 /* Tell the world that icons might have changed. We could invent a narrower-scope
6859 * signal to mean only "thumbnails might have changed" if this ends up being slow
6862 emit_change_signals_for_all_files_in_all_directories ();
6866 show_thumbnails_changed_callback (gpointer user_data
)
6868 show_image_thumbs
= eel_preferences_get_enum (NAUTILUS_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS
);
6870 /* Tell the world that icons might have changed. We could invent a narrower-scope
6871 * signal to mean only "thumbnails might have changed" if this ends up being slow
6874 emit_change_signals_for_all_files_in_all_directories ();
6878 mime_type_data_changed_callback (GObject
*signaller
, gpointer user_data
)
6880 /* Tell the world that icons might have changed. We could invent a narrower-scope
6881 * signal to mean only "thumbnails might have changed" if this ends up being slow
6884 emit_change_signals_for_all_files_in_all_directories ();
6888 icon_theme_changed_callback (GtkIconTheme
*icon_theme
,
6891 /* Clear all pixmap caches as the icon => pixmap lookup changed */
6892 nautilus_icon_info_clear_caches ();
6894 /* Tell the world that icons might have changed. We could invent a narrower-scope
6895 * signal to mean only "thumbnails might have changed" if this ends up being slow
6898 emit_change_signals_for_all_files_in_all_directories ();
6902 nautilus_file_class_init (NautilusFileClass
*class)
6904 GtkIconTheme
*icon_theme
;
6906 parent_class
= g_type_class_peek_parent (class);
6908 attribute_name_q
= g_quark_from_static_string ("name");
6909 attribute_size_q
= g_quark_from_static_string ("size");
6910 attribute_type_q
= g_quark_from_static_string ("type");
6911 attribute_modification_date_q
= g_quark_from_static_string ("modification_date");
6912 attribute_date_modified_q
= g_quark_from_static_string ("date_modified");
6913 attribute_accessed_date_q
= g_quark_from_static_string ("accessed_date");
6914 attribute_date_accessed_q
= g_quark_from_static_string ("date_accessed");
6915 attribute_emblems_q
= g_quark_from_static_string ("emblems");
6916 attribute_mime_type_q
= g_quark_from_static_string ("mime_type");
6917 attribute_size_detail_q
= g_quark_from_static_string ("size_detail");
6918 attribute_deep_size_q
= g_quark_from_static_string ("deep_size");
6919 attribute_deep_file_count_q
= g_quark_from_static_string ("deep_file_count");
6920 attribute_deep_directory_count_q
= g_quark_from_static_string ("deep_directory_count");
6921 attribute_deep_total_count_q
= g_quark_from_static_string ("deep_total_count");
6922 attribute_date_changed_q
= g_quark_from_static_string ("date_changed");
6923 attribute_date_permissions_q
= g_quark_from_static_string ("date_permissions");
6924 attribute_permissions_q
= g_quark_from_static_string ("permissions");
6925 attribute_selinux_context_q
= g_quark_from_static_string ("selinux_context");
6926 attribute_octal_permissions_q
= g_quark_from_static_string ("octal_permissions");
6927 attribute_owner_q
= g_quark_from_static_string ("owner");
6928 attribute_group_q
= g_quark_from_static_string ("group");
6929 attribute_uri_q
= g_quark_from_static_string ("uri");
6930 attribute_where_q
= g_quark_from_static_string ("where");
6931 attribute_link_target_q
= g_quark_from_static_string ("link_target");
6932 attribute_volume_q
= g_quark_from_static_string ("volume");
6933 attribute_free_space_q
= g_quark_from_static_string ("free_space");
6935 G_OBJECT_CLASS (class)->finalize
= finalize
;
6936 G_OBJECT_CLASS (class)->constructor
= nautilus_file_constructor
;
6939 g_signal_new ("changed",
6940 G_TYPE_FROM_CLASS (class),
6942 G_STRUCT_OFFSET (NautilusFileClass
, changed
),
6944 g_cclosure_marshal_VOID__VOID
,
6947 signals
[UPDATED_DEEP_COUNT_IN_PROGRESS
] =
6948 g_signal_new ("updated_deep_count_in_progress",
6949 G_TYPE_FROM_CLASS (class),
6951 G_STRUCT_OFFSET (NautilusFileClass
, updated_deep_count_in_progress
),
6953 g_cclosure_marshal_VOID__VOID
,
6956 g_type_class_add_private (class, sizeof (NautilusFileDetails
));
6959 eel_preferences_add_auto_enum (NAUTILUS_PREFERENCES_DATE_FORMAT
,
6962 thumbnail_limit_changed_callback (NULL
);
6963 eel_preferences_add_callback (NAUTILUS_PREFERENCES_IMAGE_FILE_THUMBNAIL_LIMIT
,
6964 thumbnail_limit_changed_callback
,
6966 thumbnail_size_changed_callback (NULL
);
6967 eel_preferences_add_callback (NAUTILUS_PREFERENCES_ICON_VIEW_THUMBNAIL_SIZE
,
6968 thumbnail_size_changed_callback
,
6970 show_thumbnails_changed_callback (NULL
);
6971 eel_preferences_add_callback (NAUTILUS_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS
,
6972 show_thumbnails_changed_callback
,
6975 icon_theme
= gtk_icon_theme_get_default ();
6976 g_signal_connect_object (icon_theme
,
6978 G_CALLBACK (icon_theme_changed_callback
),
6981 g_signal_connect (nautilus_signaller_get_current (),
6982 "mime_data_changed",
6983 G_CALLBACK (mime_type_data_changed_callback
),
6988 nautilus_file_add_emblem (NautilusFile
*file
,
6989 const char *emblem_name
)
6991 if (file
->details
->pending_info_providers
) {
6992 file
->details
->pending_extension_emblems
= g_list_prepend (file
->details
->pending_extension_emblems
,
6993 g_strdup (emblem_name
));
6995 file
->details
->extension_emblems
= g_list_prepend (file
->details
->extension_emblems
,
6996 g_strdup (emblem_name
));
6999 nautilus_file_changed (file
);
7003 nautilus_file_add_string_attribute (NautilusFile
*file
,
7004 const char *attribute_name
,
7007 if (file
->details
->pending_info_providers
) {
7008 /* Lazily create hashtable */
7009 if (!file
->details
->pending_extension_attributes
) {
7010 file
->details
->pending_extension_attributes
=
7011 g_hash_table_new_full (g_direct_hash
, g_direct_equal
,
7013 (GDestroyNotify
)g_free
);
7015 g_hash_table_insert (file
->details
->pending_extension_attributes
,
7016 GINT_TO_POINTER (g_quark_from_string (attribute_name
)),
7019 if (!file
->details
->extension_attributes
) {
7020 file
->details
->extension_attributes
=
7021 g_hash_table_new_full (g_direct_hash
, g_direct_equal
,
7023 (GDestroyNotify
)g_free
);
7025 g_hash_table_insert (file
->details
->extension_attributes
,
7026 GINT_TO_POINTER (g_quark_from_string (attribute_name
)),
7030 nautilus_file_changed (file
);
7034 nautilus_file_invalidate_extension_info (NautilusFile
*file
)
7036 nautilus_file_invalidate_attributes (file
, NAUTILUS_FILE_ATTRIBUTE_EXTENSION_INFO
);
7040 nautilus_file_info_providers_done (NautilusFile
*file
)
7042 eel_g_list_free_deep (file
->details
->extension_emblems
);
7043 file
->details
->extension_emblems
= file
->details
->pending_extension_emblems
;
7044 file
->details
->pending_extension_emblems
= NULL
;
7046 if (file
->details
->extension_attributes
) {
7047 g_hash_table_destroy (file
->details
->extension_attributes
);
7050 file
->details
->extension_attributes
= file
->details
->pending_extension_attributes
;
7051 file
->details
->pending_extension_attributes
= NULL
;
7053 nautilus_file_changed (file
);
7057 nautilus_file_info_iface_init (NautilusFileInfoIface
*iface
)
7059 iface
->is_gone
= nautilus_file_is_gone
;
7060 iface
->get_name
= nautilus_file_get_name
;
7061 iface
->get_file_type
= nautilus_file_get_file_type
;
7062 iface
->get_location
= nautilus_file_get_location
;
7063 iface
->get_uri
= nautilus_file_get_uri
;
7064 iface
->get_parent_location
= nautilus_file_get_parent_location
;
7065 iface
->get_parent_uri
= nautilus_file_get_parent_uri
;
7066 iface
->get_parent_info
= nautilus_file_get_parent
;
7067 iface
->get_mount
= nautilus_file_get_mount
;
7068 iface
->get_uri_scheme
= nautilus_file_get_uri_scheme
;
7069 iface
->get_activation_uri
= nautilus_file_get_activation_uri
;
7070 iface
->get_mime_type
= nautilus_file_get_mime_type
;
7071 iface
->is_mime_type
= nautilus_file_is_mime_type
;
7072 iface
->is_directory
= nautilus_file_is_directory
;
7073 iface
->can_write
= nautilus_file_can_write
;
7074 iface
->add_emblem
= nautilus_file_add_emblem
;
7075 iface
->get_string_attribute
= nautilus_file_get_string_attribute
;
7076 iface
->add_string_attribute
= nautilus_file_add_string_attribute
;
7077 iface
->invalidate_extension_info
= nautilus_file_invalidate_extension_info
;
7080 #if !defined (NAUTILUS_OMIT_SELF_CHECK)
7083 nautilus_self_check_file (void)
7085 NautilusFile
*file_1
;
7086 NautilusFile
*file_2
;
7089 /* refcount checks */
7091 EEL_CHECK_INTEGER_RESULT (nautilus_directory_number_outstanding (), 0);
7093 file_1
= nautilus_file_get_by_uri ("file:///home/");
7095 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1
)->ref_count
, 1);
7096 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1
->details
->directory
)->ref_count
, 1);
7097 EEL_CHECK_INTEGER_RESULT (nautilus_directory_number_outstanding (), 1);
7099 nautilus_file_unref (file_1
);
7101 EEL_CHECK_INTEGER_RESULT (nautilus_directory_number_outstanding (), 0);
7103 file_1
= nautilus_file_get_by_uri ("file:///etc");
7104 file_2
= nautilus_file_get_by_uri ("file:///usr");
7107 list
= g_list_prepend (list
, file_1
);
7108 list
= g_list_prepend (list
, file_2
);
7110 nautilus_file_list_ref (list
);
7112 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1
)->ref_count
, 2);
7113 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2
)->ref_count
, 2);
7115 nautilus_file_list_unref (list
);
7117 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1
)->ref_count
, 1);
7118 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2
)->ref_count
, 1);
7120 nautilus_file_list_free (list
);
7122 EEL_CHECK_INTEGER_RESULT (nautilus_directory_number_outstanding (), 0);
7126 file_1
= nautilus_file_get_by_uri ("file:///home/");
7128 EEL_CHECK_STRING_RESULT (nautilus_file_get_name (file_1
), "home");
7130 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_get_by_uri ("file:///home/") == file_1
, TRUE
);
7131 nautilus_file_unref (file_1
);
7133 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_get_by_uri ("file:///home") == file_1
, TRUE
);
7134 nautilus_file_unref (file_1
);
7136 nautilus_file_unref (file_1
);
7138 file_1
= nautilus_file_get_by_uri ("file:///home");
7139 EEL_CHECK_STRING_RESULT (nautilus_file_get_name (file_1
), "home");
7140 nautilus_file_unref (file_1
);
7143 /* ALEX: I removed this, because it was breaking distchecks.
7144 * It used to work, but when canonical uris changed from
7145 * foo: to foo:/// it broke. I don't expect it to matter
7147 file_1
= nautilus_file_get_by_uri (":");
7148 EEL_CHECK_STRING_RESULT (nautilus_file_get_name (file_1
), ":");
7149 nautilus_file_unref (file_1
);
7152 file_1
= nautilus_file_get_by_uri ("eazel:");
7153 EEL_CHECK_STRING_RESULT (nautilus_file_get_name (file_1
), "eazel");
7154 nautilus_file_unref (file_1
);
7157 file_1
= nautilus_file_get_by_uri ("file:///etc");
7158 file_2
= nautilus_file_get_by_uri ("file:///usr");
7160 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1
)->ref_count
, 1);
7161 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2
)->ref_count
, 1);
7163 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_compare_for_sort (file_1
, file_2
, NAUTILUS_FILE_SORT_BY_DISPLAY_NAME
, FALSE
, FALSE
) < 0, TRUE
);
7164 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_compare_for_sort (file_1
, file_2
, NAUTILUS_FILE_SORT_BY_DISPLAY_NAME
, FALSE
, TRUE
) > 0, TRUE
);
7165 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_compare_for_sort (file_1
, file_1
, NAUTILUS_FILE_SORT_BY_DISPLAY_NAME
, FALSE
, FALSE
) == 0, TRUE
);
7166 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_compare_for_sort (file_1
, file_1
, NAUTILUS_FILE_SORT_BY_DISPLAY_NAME
, TRUE
, FALSE
) == 0, TRUE
);
7167 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_compare_for_sort (file_1
, file_1
, NAUTILUS_FILE_SORT_BY_DISPLAY_NAME
, FALSE
, TRUE
) == 0, TRUE
);
7168 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_compare_for_sort (file_1
, file_1
, NAUTILUS_FILE_SORT_BY_DISPLAY_NAME
, TRUE
, TRUE
) == 0, TRUE
);
7170 nautilus_file_unref (file_1
);
7171 nautilus_file_unref (file_2
);
7174 #endif /* !NAUTILUS_OMIT_SELF_CHECK */