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_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory
), NULL
);
364 g_return_val_if_fail (filename
!= NULL
, NULL
);
365 g_return_val_if_fail (filename
[0] != '\0', NULL
);
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_return_val_if_fail (location
!= NULL
, 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
;
1556 if (file
->details
->is_gone
) {
1561 nautilus_file_mark_gone (file
);
1565 file
->details
->file_info_is_up_to_date
= TRUE
;
1567 /* FIXME bugzilla.gnome.org 42044: Need to let links that
1568 * point to the old name know that the file has been renamed.
1571 remove_from_link_hash_table (file
);
1575 if (!file
->details
->got_file_info
) {
1578 file
->details
->got_file_info
= TRUE
;
1580 changed
|= nautilus_file_set_display_name (file
,
1581 g_file_info_get_display_name (info
),
1582 g_file_info_get_edit_name (info
),
1585 file_type
= g_file_info_get_file_type (info
);
1586 if (file
->details
->type
!= file_type
) {
1589 file
->details
->type
= file_type
;
1591 if (!file
->details
->got_custom_activation_location
) {
1592 activation_uri
= g_file_info_get_attribute_string (info
, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI
);
1593 if (activation_uri
== NULL
) {
1594 if (file
->details
->activation_location
) {
1595 g_object_unref (file
->details
->activation_location
);
1596 file
->details
->activation_location
= NULL
;
1600 old_activation_location
= file
->details
->activation_location
;
1601 file
->details
->activation_location
= g_file_new_for_uri (activation_uri
);
1603 if (old_activation_location
) {
1604 if (!g_file_equal (old_activation_location
,
1605 file
->details
->activation_location
)) {
1608 g_object_unref (old_activation_location
);
1615 is_symlink
= g_file_info_get_is_symlink (info
);
1616 if (file
->details
->is_symlink
!= is_symlink
) {
1619 file
->details
->is_symlink
= is_symlink
;
1621 is_hidden
= g_file_info_get_is_hidden (info
);
1622 if (file
->details
->is_hidden
!= is_hidden
) {
1625 file
->details
->is_hidden
= is_hidden
;
1627 is_backup
= g_file_info_get_is_backup (info
);
1628 if (file
->details
->is_backup
!= is_backup
) {
1631 file
->details
->is_backup
= is_backup
;
1633 is_mountpoint
= g_file_info_get_attribute_boolean (info
, G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT
);
1634 if (file
->details
->is_mountpoint
!= is_mountpoint
) {
1637 file
->details
->is_mountpoint
= is_mountpoint
;
1639 has_permissions
= g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_UNIX_MODE
);
1640 permissions
= g_file_info_get_attribute_uint32 (info
, G_FILE_ATTRIBUTE_UNIX_MODE
);;
1641 if (file
->details
->has_permissions
!= has_permissions
||
1642 file
->details
->permissions
!= permissions
) {
1645 file
->details
->has_permissions
= has_permissions
;
1646 file
->details
->permissions
= permissions
;
1648 /* We default to TRUE for this if we can't know */
1656 can_unmount
= FALSE
;
1658 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_ACCESS_CAN_READ
)) {
1659 can_read
= g_file_info_get_attribute_boolean (info
,
1660 G_FILE_ATTRIBUTE_ACCESS_CAN_READ
);
1662 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE
)) {
1663 can_write
= g_file_info_get_attribute_boolean (info
,
1664 G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE
);
1666 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE
)) {
1667 can_execute
= g_file_info_get_attribute_boolean (info
,
1668 G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE
);
1670 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE
)) {
1671 can_delete
= g_file_info_get_attribute_boolean (info
,
1672 G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE
);
1674 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH
)) {
1675 can_trash
= g_file_info_get_attribute_boolean (info
,
1676 G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH
);
1678 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME
)) {
1679 can_rename
= g_file_info_get_attribute_boolean (info
,
1680 G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME
);
1682 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT
)) {
1683 can_mount
= g_file_info_get_attribute_boolean (info
,
1684 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_MOUNT
);
1686 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT
)) {
1687 can_unmount
= g_file_info_get_attribute_boolean (info
,
1688 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT
);
1690 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT
)) {
1691 can_eject
= g_file_info_get_attribute_boolean (info
,
1692 G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT
);
1694 if (file
->details
->can_read
!= can_read
||
1695 file
->details
->can_write
!= can_write
||
1696 file
->details
->can_execute
!= can_execute
||
1697 file
->details
->can_delete
!= can_delete
||
1698 file
->details
->can_trash
!= can_trash
||
1699 file
->details
->can_rename
!= can_rename
||
1700 file
->details
->can_mount
!= can_mount
||
1701 file
->details
->can_unmount
!= can_unmount
||
1702 file
->details
->can_eject
!= can_eject
) {
1706 file
->details
->can_read
= can_read
;
1707 file
->details
->can_write
= can_write
;
1708 file
->details
->can_execute
= can_execute
;
1709 file
->details
->can_delete
= can_delete
;
1710 file
->details
->can_trash
= can_trash
;
1711 file
->details
->can_rename
= can_rename
;
1712 file
->details
->can_mount
= can_mount
;
1713 file
->details
->can_unmount
= can_unmount
;
1714 file
->details
->can_eject
= can_eject
;
1718 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_UNIX_UID
)) {
1719 uid
= g_file_info_get_attribute_uint32 (info
, G_FILE_ATTRIBUTE_UNIX_UID
);
1721 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_UNIX_GID
)) {
1722 gid
= g_file_info_get_attribute_uint32 (info
, G_FILE_ATTRIBUTE_UNIX_GID
);
1724 if (file
->details
->uid
!= uid
||
1725 file
->details
->gid
!= gid
) {
1728 file
->details
->uid
= uid
;
1729 file
->details
->gid
= gid
;
1732 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_STANDARD_SIZE
)) {
1733 size
= g_file_info_get_size (info
);
1735 if (file
->details
->size
!= size
) {
1738 file
->details
->size
= size
;
1740 sort_order
= g_file_info_get_sort_order (info
);
1741 if (file
->details
->sort_order
!= sort_order
) {
1744 file
->details
->sort_order
= sort_order
;
1746 atime
= g_file_info_get_attribute_uint64 (info
, G_FILE_ATTRIBUTE_TIME_ACCESS
);
1747 ctime
= g_file_info_get_attribute_uint64 (info
, G_FILE_ATTRIBUTE_TIME_CHANGED
);
1748 mtime
= g_file_info_get_attribute_uint64 (info
, G_FILE_ATTRIBUTE_TIME_MODIFIED
);
1749 if (file
->details
->atime
!= atime
||
1750 file
->details
->mtime
!= mtime
||
1751 file
->details
->ctime
!= ctime
) {
1754 file
->details
->atime
= atime
;
1755 file
->details
->ctime
= ctime
;
1756 file
->details
->mtime
= mtime
;
1758 if (file
->details
->thumbnail
!= NULL
&&
1759 file
->details
->thumbnail_mtime
!= 0 &&
1760 file
->details
->thumbnail_mtime
!= mtime
) {
1761 file
->details
->thumbnail_is_up_to_date
= FALSE
;
1765 icon
= g_file_info_get_icon (info
);
1766 if (!g_icon_equal (icon
, file
->details
->icon
)) {
1769 if (file
->details
->icon
) {
1770 g_object_unref (file
->details
->icon
);
1772 file
->details
->icon
= g_object_ref (icon
);
1775 thumbnail_path
= g_file_info_get_attribute_byte_string (info
, G_FILE_ATTRIBUTE_THUMBNAIL_PATH
);
1776 if (eel_strcmp (file
->details
->thumbnail_path
, thumbnail_path
) != 0) {
1778 g_free (file
->details
->thumbnail_path
);
1779 file
->details
->thumbnail_path
= g_strdup (thumbnail_path
);
1782 thumbnailing_failed
= g_file_info_get_attribute_boolean (info
, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED
);
1783 if (file
->details
->thumbnailing_failed
!= thumbnailing_failed
) {
1785 file
->details
->thumbnailing_failed
= thumbnailing_failed
;
1788 symlink_name
= g_file_info_get_symlink_target (info
);
1789 if (eel_strcmp (file
->details
->symlink_name
, symlink_name
) != 0) {
1791 g_free (file
->details
->symlink_name
);
1792 file
->details
->symlink_name
= g_strdup (symlink_name
);
1795 mime_type
= g_file_info_get_content_type (info
);
1796 if (eel_strcmp (eel_ref_str_peek (file
->details
->mime_type
), mime_type
) != 0) {
1799 eel_ref_str_unref (file
->details
->mime_type
);
1800 file
->details
->mime_type
= eel_ref_str_get_unique (mime_type
);
1802 selinux_context
= g_file_info_get_attribute_string (info
, G_FILE_ATTRIBUTE_SELINUX_CONTEXT
);
1803 if (eel_strcmp (file
->details
->selinux_context
, selinux_context
) != 0) {
1805 g_free (file
->details
->selinux_context
);
1806 file
->details
->selinux_context
= g_strdup (selinux_context
);
1810 name
= g_file_info_get_name (info
);
1811 if (file
->details
->name
== NULL
||
1812 strcmp (eel_ref_str_peek (file
->details
->name
), name
) != 0) {
1813 node
= nautilus_directory_begin_file_name_change
1814 (file
->details
->directory
, file
);
1816 eel_ref_str_unref (file
->details
->name
);
1817 if (eel_strcmp (eel_ref_str_peek (file
->details
->display_name
),
1819 file
->details
->name
= eel_ref_str_ref (file
->details
->display_name
);
1821 file
->details
->name
= eel_ref_str_new (name
);
1824 nautilus_directory_end_file_name_change
1825 (file
->details
->directory
, file
, node
);
1830 add_to_link_hash_table (file
);
1832 update_links_if_target (file
);
1839 update_info_and_name (NautilusFile
*file
,
1842 return update_info_internal (file
, info
, TRUE
);
1846 nautilus_file_update_info (NautilusFile
*file
,
1849 return update_info_internal (file
, info
, FALSE
);
1853 update_name_internal (NautilusFile
*file
,
1855 gboolean in_directory
)
1859 g_assert (name
!= NULL
);
1861 if (file
->details
->is_gone
) {
1865 if (name_is (file
, name
)) {
1871 node
= nautilus_directory_begin_file_name_change
1872 (file
->details
->directory
, file
);
1875 eel_ref_str_unref (file
->details
->name
);
1876 file
->details
->name
= eel_ref_str_new (name
);
1879 nautilus_directory_end_file_name_change
1880 (file
->details
->directory
, file
, node
);
1887 nautilus_file_update_name (NautilusFile
*file
, const char *name
)
1891 ret
= update_name_internal (file
, name
, TRUE
);
1894 update_links_if_target (file
);
1901 nautilus_file_update_name_and_directory (NautilusFile
*file
,
1903 NautilusDirectory
*new_directory
)
1905 NautilusDirectory
*old_directory
;
1906 FileMonitors
*monitors
;
1908 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
1909 g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (file
->details
->directory
), FALSE
);
1910 g_return_val_if_fail (!file
->details
->is_gone
, FALSE
);
1911 g_return_val_if_fail (!nautilus_file_is_self_owned (file
), FALSE
);
1912 g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (new_directory
), FALSE
);
1914 old_directory
= file
->details
->directory
;
1915 if (old_directory
== new_directory
) {
1917 return update_name_internal (file
, name
, TRUE
);
1923 nautilus_file_ref (file
);
1925 /* FIXME bugzilla.gnome.org 42044: Need to let links that
1926 * point to the old name know that the file has been moved.
1929 remove_from_link_hash_table (file
);
1931 monitors
= nautilus_directory_remove_file_monitors (old_directory
, file
);
1932 nautilus_directory_remove_file (old_directory
, file
);
1934 file
->details
->directory
= nautilus_directory_ref (new_directory
);
1935 nautilus_directory_unref (old_directory
);
1938 update_name_internal (file
, name
, FALSE
);
1941 nautilus_directory_add_file (new_directory
, file
);
1942 nautilus_directory_add_file_monitors (new_directory
, file
, monitors
);
1944 add_to_link_hash_table (file
);
1946 update_links_if_target (file
);
1948 nautilus_file_unref (file
);
1954 nautilus_file_set_directory (NautilusFile
*file
,
1955 NautilusDirectory
*new_directory
)
1957 nautilus_file_update_name_and_directory (file
, NULL
, new_directory
);
1961 get_item_count (NautilusFile
*file
,
1964 gboolean known
, unreadable
;
1966 known
= nautilus_file_get_directory_item_count
1967 (file
, count
, &unreadable
);
1978 get_size (NautilusFile
*file
,
1981 /* If we tried and failed, then treat it like there is no size
1984 if (file
->details
->get_info_failed
) {
1988 /* If the info is NULL that means we haven't even tried yet,
1989 * so it's just unknown, not unknowable.
1991 if (!file
->details
->got_file_info
) {
1995 /* If we got info with no size in it, it means there is no
1996 * such thing as a size as far as gnome-vfs is concerned,
1999 if (file
->details
->size
== -1) {
2003 /* We have a size! */
2004 *size
= file
->details
->size
;
2009 get_time (NautilusFile
*file
,
2011 NautilusDateType type
)
2015 /* If we tried and failed, then treat it like there is no size
2018 if (file
->details
->get_info_failed
) {
2022 /* If the info is NULL that means we haven't even tried yet,
2023 * so it's just unknown, not unknowable.
2025 if (!file
->details
->got_file_info
) {
2031 case NAUTILUS_DATE_TYPE_MODIFIED
:
2032 time
= file
->details
->mtime
;
2034 case NAUTILUS_DATE_TYPE_ACCESSED
:
2035 time
= file
->details
->atime
;
2038 g_assert_not_reached ();
2044 /* If we got info with no modification time in it, it means
2045 * there is no such thing as a modification time as far as
2046 * gnome-vfs is concerned, so "unknowable".
2055 compare_directories_by_count (NautilusFile
*file_1
, NautilusFile
*file_2
)
2058 * Directories with unknown # of items
2059 * Directories with "unknowable" # of items
2060 * Directories with 0 items
2061 * Directories with n items
2064 Knowledge count_known_1
, count_known_2
;
2065 guint count_1
, count_2
;
2067 count_known_1
= get_item_count (file_1
, &count_1
);
2068 count_known_2
= get_item_count (file_2
, &count_2
);
2070 if (count_known_1
> count_known_2
) {
2073 if (count_known_1
< count_known_2
) {
2077 /* count_known_1 and count_known_2 are equal now. Check if count
2078 * details are UNKNOWABLE or UNKNOWN.
2080 if (count_known_1
== UNKNOWABLE
|| count_known_1
== UNKNOWN
) {
2084 if (count_1
< count_2
) {
2087 if (count_1
> count_2
) {
2095 compare_files_by_size (NautilusFile
*file_1
, NautilusFile
*file_2
)
2098 * Files with unknown size.
2099 * Files with "unknowable" size.
2100 * Files with smaller sizes.
2101 * Files with large sizes.
2104 Knowledge size_known_1
, size_known_2
;
2105 goffset size_1
, size_2
;
2107 size_known_1
= get_size (file_1
, &size_1
);
2108 size_known_2
= get_size (file_2
, &size_2
);
2110 if (size_known_1
> size_known_2
) {
2113 if (size_known_1
< size_known_2
) {
2117 /* size_known_1 and size_known_2 are equal now. Check if size
2118 * details are UNKNOWABLE or UNKNOWN
2120 if (size_known_1
== UNKNOWABLE
|| size_known_1
== UNKNOWN
) {
2124 if (size_1
< size_2
) {
2127 if (size_1
> size_2
) {
2135 compare_by_size (NautilusFile
*file_1
, NautilusFile
*file_2
)
2138 * Directories with n items
2139 * Directories with 0 items
2140 * Directories with "unknowable" # of items
2141 * Directories with unknown # of items
2142 * Files with large sizes.
2143 * Files with smaller sizes.
2144 * Files with "unknowable" size.
2145 * Files with unknown size.
2148 gboolean is_directory_1
, is_directory_2
;
2150 is_directory_1
= nautilus_file_is_directory (file_1
);
2151 is_directory_2
= nautilus_file_is_directory (file_2
);
2153 if (is_directory_1
&& !is_directory_2
) {
2156 if (is_directory_2
&& !is_directory_1
) {
2160 if (is_directory_1
) {
2161 return compare_directories_by_count (file_1
, file_2
);
2163 return compare_files_by_size (file_1
, file_2
);
2168 compare_by_display_name (NautilusFile
*file_1
, NautilusFile
*file_2
)
2170 const char *name_1
, *name_2
;
2171 const char *key_1
, *key_2
;
2172 gboolean sort_last_1
, sort_last_2
;
2175 name_1
= nautilus_file_peek_display_name (file_1
);
2176 name_2
= nautilus_file_peek_display_name (file_2
);
2178 sort_last_1
= name_1
[0] == SORT_LAST_CHAR1
|| name_1
[0] == SORT_LAST_CHAR2
;
2179 sort_last_2
= name_2
[0] == SORT_LAST_CHAR1
|| name_2
[0] == SORT_LAST_CHAR2
;
2181 if (sort_last_1
&& !sort_last_2
) {
2183 } else if (!sort_last_1
&& sort_last_2
) {
2186 key_1
= nautilus_file_peek_display_name_collation_key (file_1
);
2187 key_2
= nautilus_file_peek_display_name_collation_key (file_2
);
2188 compare
= strcmp (key_1
, key_2
);
2195 compare_by_directory_name (NautilusFile
*file_1
, NautilusFile
*file_2
)
2197 char *directory_1
, *directory_2
;
2200 if (file_1
->details
->directory
== file_2
->details
->directory
) {
2204 directory_1
= nautilus_file_get_parent_uri_for_display (file_1
);
2205 directory_2
= nautilus_file_get_parent_uri_for_display (file_2
);
2207 compare
= g_utf8_collate (directory_1
, directory_2
);
2209 g_free (directory_1
);
2210 g_free (directory_2
);
2216 file_has_note (NautilusFile
*file
)
2221 note
= nautilus_file_get_metadata (file
, NAUTILUS_METADATA_KEY_ANNOTATION
, NULL
);
2222 res
= note
!= NULL
&& note
[0] != 0;
2229 prepend_automatic_keywords (NautilusFile
*file
,
2232 /* Prepend in reverse order. */
2233 NautilusFile
*parent
;
2235 parent
= nautilus_file_get_parent (file
);
2237 #ifdef TRASH_IS_FAST_ENOUGH
2238 if (nautilus_file_is_in_trash (file
)) {
2239 names
= g_list_prepend
2240 (names
, g_strdup (NAUTILUS_FILE_EMBLEM_NAME_TRASH
));
2243 if (nautilus_file_is_desktop_directory (file
)) {
2244 names
= g_list_prepend
2245 (names
, g_strdup (NAUTILUS_FILE_EMBLEM_NAME_DESKTOP
));
2247 if (file_has_note (file
)) {
2248 names
= g_list_prepend
2249 (names
, g_strdup (NAUTILUS_FILE_EMBLEM_NAME_NOTE
));
2251 if (!nautilus_file_can_write (file
) &&
2252 (parent
== NULL
|| nautilus_file_can_write (parent
))) {
2253 names
= g_list_prepend
2254 (names
, g_strdup (NAUTILUS_FILE_EMBLEM_NAME_CANT_WRITE
));
2256 if (!nautilus_file_can_read (file
)) {
2257 names
= g_list_prepend
2258 (names
, g_strdup (NAUTILUS_FILE_EMBLEM_NAME_CANT_READ
));
2260 if (nautilus_file_is_symbolic_link (file
)) {
2261 names
= g_list_prepend
2262 (names
, g_strdup (NAUTILUS_FILE_EMBLEM_NAME_SYMBOLIC_LINK
));
2266 nautilus_file_unref (parent
);
2274 fill_emblem_cache_if_needed (NautilusFile
*file
)
2276 GList
*node
, *keywords
;
2280 if (file
->details
->compare_by_emblem_cache
!= NULL
) {
2281 /* Got a cache already. */
2285 keywords
= nautilus_file_get_keywords (file
);
2287 /* Add up the keyword string lengths */
2289 for (node
= keywords
; node
!= NULL
; node
= node
->next
) {
2290 length
+= strlen ((const char *) node
->data
) + 1;
2293 /* Now that we know how large the cache struct needs to be, allocate it. */
2294 file
->details
->compare_by_emblem_cache
= g_malloc (sizeof(NautilusFileSortByEmblemCache
) + length
);
2296 /* Copy them into the cache. */
2297 scanner
= file
->details
->compare_by_emblem_cache
->emblem_keywords
;
2298 for (node
= keywords
; node
!= NULL
; node
= node
->next
) {
2299 length
= strlen ((const char *) node
->data
) + 1;
2300 memcpy (scanner
, (const char *) node
->data
, length
);
2304 /* Zero-terminate so we can tell where the list ends. */
2307 eel_g_list_free_deep (keywords
);
2311 compare_by_emblems (NautilusFile
*file_1
, NautilusFile
*file_2
)
2313 const char *keyword_cache_1
, *keyword_cache_2
;
2317 fill_emblem_cache_if_needed (file_1
);
2318 fill_emblem_cache_if_needed (file_2
);
2320 /* We ignore automatic emblems, and only sort by user-added keywords. */
2322 keyword_cache_1
= file_1
->details
->compare_by_emblem_cache
->emblem_keywords
;
2323 keyword_cache_2
= file_2
->details
->compare_by_emblem_cache
->emblem_keywords
;
2324 for (; *keyword_cache_1
!= '\0' && *keyword_cache_2
!= '\0';) {
2325 compare_result
= g_utf8_collate (keyword_cache_1
, keyword_cache_2
);
2326 if (compare_result
!= 0) {
2327 return compare_result
;
2330 /* Advance to the next keyword */
2331 length
= strlen (keyword_cache_1
);
2332 keyword_cache_1
+= length
+ 1;
2333 keyword_cache_2
+= length
+ 1;
2337 /* One or both is now NULL. */
2338 if (*keyword_cache_1
!= '\0') {
2339 g_assert (*keyword_cache_2
== '\0');
2341 } else if (*keyword_cache_2
!= '\0') {
2349 compare_by_type (NautilusFile
*file_1
, NautilusFile
*file_2
)
2351 gboolean is_directory_1
;
2352 gboolean is_directory_2
;
2353 char *type_string_1
;
2354 char *type_string_2
;
2357 /* Directories go first. Then, if mime types are identical,
2358 * don't bother getting strings (for speed). This assumes
2359 * that the string is dependent entirely on the mime type,
2360 * which is true now but might not be later.
2362 is_directory_1
= nautilus_file_is_directory (file_1
);
2363 is_directory_2
= nautilus_file_is_directory (file_2
);
2365 if (is_directory_1
&& is_directory_2
) {
2369 if (is_directory_1
) {
2373 if (is_directory_2
) {
2377 if (file_1
->details
->mime_type
!= NULL
&&
2378 file_2
->details
->mime_type
!= NULL
&&
2379 strcmp (eel_ref_str_peek (file_1
->details
->mime_type
),
2380 eel_ref_str_peek (file_2
->details
->mime_type
)) == 0) {
2384 type_string_1
= nautilus_file_get_type_as_string (file_1
);
2385 type_string_2
= nautilus_file_get_type_as_string (file_2
);
2387 result
= g_utf8_collate (type_string_1
, type_string_2
);
2389 g_free (type_string_1
);
2390 g_free (type_string_2
);
2396 compare_by_time (NautilusFile
*file_1
, NautilusFile
*file_2
, NautilusDateType type
)
2399 * Files with unknown times.
2400 * Files with "unknowable" times.
2401 * Files with older times.
2402 * Files with newer times.
2405 Knowledge time_known_1
, time_known_2
;
2406 time_t time_1
, time_2
;
2408 time_known_1
= get_time (file_1
, &time_1
, type
);
2409 time_known_2
= get_time (file_2
, &time_2
, type
);
2411 if (time_known_1
> time_known_2
) {
2414 if (time_known_1
< time_known_2
) {
2418 /* Now time_known_1 is equal to time_known_2. Check whether
2419 * we failed to get modification times for files
2421 if(time_known_1
== UNKNOWABLE
|| time_known_1
== UNKNOWN
) {
2425 if (time_1
< time_2
) {
2428 if (time_1
> time_2
) {
2436 compare_by_full_path (NautilusFile
*file_1
, NautilusFile
*file_2
)
2440 compare
= compare_by_directory_name (file_1
, file_2
);
2444 return compare_by_display_name (file_1
, file_2
);
2448 nautilus_file_compare_for_sort_internal (NautilusFile
*file_1
,
2449 NautilusFile
*file_2
,
2450 gboolean directories_first
)
2452 gboolean is_directory_1
, is_directory_2
;
2454 if (directories_first
) {
2455 is_directory_1
= nautilus_file_is_directory (file_1
);
2456 is_directory_2
= nautilus_file_is_directory (file_2
);
2458 if (is_directory_1
&& !is_directory_2
) {
2462 if (is_directory_2
&& !is_directory_1
) {
2467 if (file_1
->details
->sort_order
< file_2
->details
->sort_order
) {
2469 } else if (file_1
->details
->sort_order
> file_2
->details
->sort_order
) {
2477 * nautilus_file_compare_for_sort:
2478 * @file_1: A file object
2479 * @file_2: Another file object
2480 * @sort_type: Sort criterion
2481 * @directories_first: Put all directories before any non-directories
2482 * @reversed: Reverse the order of the items, except that
2483 * the directories_first flag is still respected.
2485 * Return value: int < 0 if @file_1 should come before file_2 in a
2486 * sorted list; int > 0 if @file_2 should come before file_1 in a
2487 * sorted list; 0 if @file_1 and @file_2 are equal for this sort criterion. Note
2488 * that each named sort type may actually break ties several ways, with the name
2489 * of the sort criterion being the primary but not only differentiator.
2492 nautilus_file_compare_for_sort (NautilusFile
*file_1
,
2493 NautilusFile
*file_2
,
2494 NautilusFileSortType sort_type
,
2495 gboolean directories_first
,
2500 if (file_1
== file_2
) {
2504 result
= nautilus_file_compare_for_sort_internal (file_1
, file_2
, directories_first
);
2507 switch (sort_type
) {
2508 case NAUTILUS_FILE_SORT_BY_DISPLAY_NAME
:
2509 result
= compare_by_display_name (file_1
, file_2
);
2511 result
= compare_by_directory_name (file_1
, file_2
);
2514 case NAUTILUS_FILE_SORT_BY_DIRECTORY
:
2515 result
= compare_by_full_path (file_1
, file_2
);
2517 case NAUTILUS_FILE_SORT_BY_SIZE
:
2518 /* Compare directory sizes ourselves, then if necessary
2519 * use GnomeVFS to compare file sizes.
2521 result
= compare_by_size (file_1
, file_2
);
2523 result
= compare_by_full_path (file_1
, file_2
);
2526 case NAUTILUS_FILE_SORT_BY_TYPE
:
2527 /* GnomeVFS doesn't know about our special text for certain
2528 * mime types, so we handle the mime-type sorting ourselves.
2530 result
= compare_by_type (file_1
, file_2
);
2532 result
= compare_by_full_path (file_1
, file_2
);
2535 case NAUTILUS_FILE_SORT_BY_MTIME
:
2536 result
= compare_by_time (file_1
, file_2
, NAUTILUS_DATE_TYPE_MODIFIED
);
2538 result
= compare_by_full_path (file_1
, file_2
);
2541 case NAUTILUS_FILE_SORT_BY_ATIME
:
2542 result
= compare_by_time (file_1
, file_2
, NAUTILUS_DATE_TYPE_ACCESSED
);
2544 result
= compare_by_full_path (file_1
, file_2
);
2547 case NAUTILUS_FILE_SORT_BY_EMBLEMS
:
2548 /* GnomeVFS doesn't know squat about our emblems, so
2549 * we handle comparing them here, before falling back
2552 result
= compare_by_emblems (file_1
, file_2
);
2554 result
= compare_by_full_path (file_1
, file_2
);
2558 g_return_val_if_reached (0);
2570 nautilus_file_compare_for_sort_by_attribute_q (NautilusFile
*file_1
,
2571 NautilusFile
*file_2
,
2573 gboolean directories_first
,
2578 if (file_1
== file_2
) {
2582 /* Convert certain attributes into NautilusFileSortTypes and use
2583 * nautilus_file_compare_for_sort()
2585 if (attribute
== 0 || attribute
== attribute_name_q
) {
2586 return nautilus_file_compare_for_sort (file_1
, file_2
,
2587 NAUTILUS_FILE_SORT_BY_DISPLAY_NAME
,
2590 } else if (attribute
== attribute_size_q
) {
2591 return nautilus_file_compare_for_sort (file_1
, file_2
,
2592 NAUTILUS_FILE_SORT_BY_SIZE
,
2595 } else if (attribute
== attribute_type_q
) {
2596 return nautilus_file_compare_for_sort (file_1
, file_2
,
2597 NAUTILUS_FILE_SORT_BY_TYPE
,
2600 } else if (attribute
== attribute_modification_date_q
|| attribute
== attribute_date_modified_q
) {
2601 return nautilus_file_compare_for_sort (file_1
, file_2
,
2602 NAUTILUS_FILE_SORT_BY_MTIME
,
2605 } else if (attribute
== attribute_accessed_date_q
|| attribute
== attribute_date_accessed_q
) {
2606 return nautilus_file_compare_for_sort (file_1
, file_2
,
2607 NAUTILUS_FILE_SORT_BY_ATIME
,
2610 } else if (attribute
== attribute_emblems_q
) {
2611 return nautilus_file_compare_for_sort (file_1
, file_2
,
2612 NAUTILUS_FILE_SORT_BY_EMBLEMS
,
2617 /* it is a normal attribute, compare by strings */
2619 result
= nautilus_file_compare_for_sort_internal (file_1
, file_2
, directories_first
);
2625 value_1
= nautilus_file_get_string_attribute_q (file_1
,
2627 value_2
= nautilus_file_get_string_attribute_q (file_2
,
2630 if (value_1
!= NULL
&& value_2
!= NULL
) {
2631 result
= strcmp (value_1
, value_2
);
2646 nautilus_file_compare_for_sort_by_attribute (NautilusFile
*file_1
,
2647 NautilusFile
*file_2
,
2648 const char *attribute
,
2649 gboolean directories_first
,
2652 return nautilus_file_compare_for_sort_by_attribute_q (file_1
, file_2
,
2653 g_quark_from_string (attribute
),
2660 * nautilus_file_compare_name:
2661 * @file: A file object
2662 * @pattern: A string we are comparing it with
2664 * Return value: result of a comparison of the file name and the given pattern,
2665 * using the same sorting order as sort by name.
2668 nautilus_file_compare_display_name (NautilusFile
*file
,
2669 const char *pattern
)
2674 g_return_val_if_fail (pattern
!= NULL
, -1);
2676 name
= nautilus_file_peek_display_name (file
);
2677 result
= g_utf8_collate (name
, pattern
);
2683 nautilus_file_is_hidden_file (NautilusFile
*file
)
2685 return file
->details
->is_hidden
;
2689 nautilus_file_is_backup_file (NautilusFile
*file
)
2691 return file
->details
->is_backup
;
2695 is_file_hidden (NautilusFile
*file
)
2697 return file
->details
->directory
->details
->hidden_file_hash
!= NULL
&&
2698 g_hash_table_lookup (file
->details
->directory
->details
->hidden_file_hash
,
2699 eel_ref_str_peek (file
->details
->name
)) != NULL
;
2704 nautilus_file_should_show (NautilusFile
*file
,
2705 gboolean show_hidden
,
2706 gboolean show_backup
)
2708 return (show_hidden
|| (!nautilus_file_is_hidden_file (file
) && !is_file_hidden (file
))) &&
2709 (show_backup
|| !nautilus_file_is_backup_file (file
));
2714 nautilus_file_is_home (NautilusFile
*file
)
2718 dir
= file
->details
->directory
->details
->location
;
2723 return nautilus_is_home_directory_file (dir
,
2724 eel_ref_str_peek (file
->details
->name
));
2728 nautilus_file_is_in_desktop (NautilusFile
*file
)
2730 if (file
->details
->directory
->details
->location
) {
2731 return nautilus_is_desktop_directory (file
->details
->directory
->details
->location
);
2738 filter_hidden_and_backup_partition_callback (gpointer data
,
2739 gpointer callback_data
)
2742 FilterOptions options
;
2744 file
= NAUTILUS_FILE (data
);
2745 options
= GPOINTER_TO_INT (callback_data
);
2747 return nautilus_file_should_show (file
,
2748 options
& SHOW_HIDDEN
,
2749 options
& SHOW_BACKUP
);
2753 nautilus_file_list_filter_hidden_and_backup (GList
*files
,
2754 gboolean show_hidden
,
2755 gboolean show_backup
)
2757 GList
*filtered_files
;
2758 GList
*removed_files
;
2760 /* FIXME bugzilla.gnome.org 40653:
2761 * Eventually this should become a generic filtering thingy.
2764 filtered_files
= nautilus_file_list_copy (files
);
2765 filtered_files
= eel_g_list_partition (filtered_files
,
2766 filter_hidden_and_backup_partition_callback
,
2767 GINT_TO_POINTER ((show_hidden
? SHOW_HIDDEN
: 0) |
2768 (show_backup
? SHOW_BACKUP
: 0)),
2770 nautilus_file_list_free (removed_files
);
2772 return filtered_files
;
2778 /* We use the file's URI for the metadata for files in a directory,
2779 * but we use a hard-coded string for the metadata for the directory
2783 get_metadata_name (NautilusFile
*file
)
2785 if (nautilus_file_is_self_owned (file
)) {
2786 return FILE_NAME_FOR_DIRECTORY_METADATA
;
2788 return eel_ref_str_peek (file
->details
->name
);
2792 nautilus_file_get_metadata (NautilusFile
*file
,
2794 const char *default_metadata
)
2796 g_return_val_if_fail (key
!= NULL
, g_strdup (default_metadata
));
2797 g_return_val_if_fail (key
[0] != '\0', g_strdup (default_metadata
));
2799 return g_strdup (default_metadata
);
2801 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), g_strdup (default_metadata
));
2803 return nautilus_directory_get_file_metadata
2804 (file
->details
->directory
,
2805 get_metadata_name (file
),
2811 nautilus_file_get_metadata_list (NautilusFile
*file
,
2812 const char *list_key
,
2813 const char *list_subkey
)
2815 g_return_val_if_fail (list_key
!= NULL
, NULL
);
2816 g_return_val_if_fail (list_key
[0] != '\0', NULL
);
2817 g_return_val_if_fail (list_subkey
!= NULL
, NULL
);
2818 g_return_val_if_fail (list_subkey
[0] != '\0', NULL
);
2822 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
2824 return nautilus_directory_get_file_metadata_list
2825 (file
->details
->directory
,
2826 get_metadata_name (file
),
2832 nautilus_file_set_metadata (NautilusFile
*file
,
2834 const char *default_metadata
,
2835 const char *metadata
)
2837 g_return_if_fail (NAUTILUS_IS_FILE (file
));
2838 g_return_if_fail (key
!= NULL
);
2839 g_return_if_fail (key
[0] != '\0');
2841 nautilus_directory_set_file_metadata
2842 (file
->details
->directory
,
2843 get_metadata_name (file
),
2850 nautilus_file_set_metadata_list (NautilusFile
*file
,
2851 const char *list_key
,
2852 const char *list_subkey
,
2855 g_return_if_fail (NAUTILUS_IS_FILE (file
));
2856 g_return_if_fail (list_key
!= NULL
);
2857 g_return_if_fail (list_key
[0] != '\0');
2858 g_return_if_fail (list_subkey
!= NULL
);
2859 g_return_if_fail (list_subkey
[0] != '\0');
2861 nautilus_directory_set_file_metadata_list
2862 (file
->details
->directory
,
2863 get_metadata_name (file
),
2871 nautilus_file_get_boolean_metadata (NautilusFile
*file
,
2873 gboolean default_metadata
)
2875 g_return_val_if_fail (key
!= NULL
, default_metadata
);
2876 g_return_val_if_fail (key
[0] != '\0', default_metadata
);
2878 return default_metadata
;
2880 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), default_metadata
);
2882 return nautilus_directory_get_boolean_file_metadata
2883 (file
->details
->directory
,
2884 get_metadata_name (file
),
2890 nautilus_file_get_integer_metadata (NautilusFile
*file
,
2892 int default_metadata
)
2894 g_return_val_if_fail (key
!= NULL
, default_metadata
);
2895 g_return_val_if_fail (key
[0] != '\0', default_metadata
);
2897 return default_metadata
;
2899 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), default_metadata
);
2901 return nautilus_directory_get_integer_file_metadata
2902 (file
->details
->directory
,
2903 get_metadata_name (file
),
2910 nautilus_file_set_boolean_metadata (NautilusFile
*file
,
2912 gboolean default_metadata
,
2915 g_return_if_fail (NAUTILUS_IS_FILE (file
));
2916 g_return_if_fail (key
!= NULL
);
2917 g_return_if_fail (key
[0] != '\0');
2919 nautilus_directory_set_boolean_file_metadata
2920 (file
->details
->directory
,
2921 get_metadata_name (file
),
2928 nautilus_file_set_integer_metadata (NautilusFile
*file
,
2930 int default_metadata
,
2933 g_return_if_fail (NAUTILUS_IS_FILE (file
));
2934 g_return_if_fail (key
!= NULL
);
2935 g_return_if_fail (key
[0] != '\0');
2937 nautilus_directory_set_integer_file_metadata
2938 (file
->details
->directory
,
2939 get_metadata_name (file
),
2946 nautilus_file_peek_display_name_collation_key (NautilusFile
*file
)
2950 res
= file
->details
->display_name_collation_key
;
2958 nautilus_file_peek_display_name (NautilusFile
*file
)
2963 /* Default to display name based on filename if its not set yet */
2965 if (file
->details
->display_name
== NULL
) {
2966 name
= eel_ref_str_peek (file
->details
->name
);
2967 if (g_utf8_validate (name
, -1, NULL
)) {
2968 nautilus_file_set_display_name (file
,
2973 escaped_name
= g_uri_escape_string (name
, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH
, TRUE
);
2974 nautilus_file_set_display_name (file
,
2978 g_free (escaped_name
);
2982 return eel_ref_str_peek (file
->details
->display_name
);
2986 nautilus_file_get_display_name (NautilusFile
*file
)
2988 return g_strdup (nautilus_file_peek_display_name (file
));
2992 nautilus_file_get_edit_name (NautilusFile
*file
)
2996 res
= eel_ref_str_peek (file
->details
->edit_name
);
3000 return g_strdup (res
);
3004 nautilus_file_get_name (NautilusFile
*file
)
3006 return g_strdup (eel_ref_str_peek (file
->details
->name
));
3010 nautilus_file_monitor_add (NautilusFile
*file
,
3011 gconstpointer client
,
3012 NautilusFileAttributes attributes
)
3014 g_return_if_fail (NAUTILUS_IS_FILE (file
));
3015 g_return_if_fail (client
!= NULL
);
3018 (NAUTILUS_FILE_CLASS
, file
,
3019 monitor_add
, (file
, client
, attributes
));
3023 nautilus_file_monitor_remove (NautilusFile
*file
,
3024 gconstpointer client
)
3026 g_return_if_fail (NAUTILUS_IS_FILE (file
));
3027 g_return_if_fail (client
!= NULL
);
3030 (NAUTILUS_FILE_CLASS
, file
,
3031 monitor_remove
, (file
, client
));
3035 nautilus_file_is_launcher (NautilusFile
*file
)
3037 return file
->details
->is_launcher
;
3041 nautilus_file_has_activation_uri (NautilusFile
*file
)
3043 return file
->details
->activation_location
!= NULL
;
3047 /* Return the uri associated with the passed-in file, which may not be
3048 * the actual uri if the file is an desktop file or a nautilus
3052 nautilus_file_get_activation_uri (NautilusFile
*file
)
3054 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
3056 if (file
->details
->activation_location
!= NULL
) {
3057 return g_file_get_uri (file
->details
->activation_location
);
3060 return nautilus_file_get_uri (file
);
3064 nautilus_file_get_activation_location (NautilusFile
*file
)
3066 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
3068 if (file
->details
->activation_location
!= NULL
) {
3069 return g_object_ref (file
->details
->activation_location
);
3072 return nautilus_file_get_location (file
);
3077 nautilus_file_get_drop_target_uri (NautilusFile
*file
)
3079 char *uri
, *target_uri
;
3081 NautilusDesktopLink
*link
;
3083 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
3085 if (NAUTILUS_IS_DESKTOP_ICON_FILE (file
)) {
3086 link
= nautilus_desktop_icon_file_get_link (NAUTILUS_DESKTOP_ICON_FILE (file
));
3089 location
= nautilus_desktop_link_get_activation_location (link
);
3090 g_object_unref (link
);
3091 if (location
!= NULL
) {
3092 uri
= g_file_get_uri (location
);
3093 g_object_unref (location
);
3099 uri
= nautilus_file_get_uri (file
);
3101 /* Check for Nautilus link */
3102 if (nautilus_file_is_nautilus_link (file
)) {
3103 location
= nautilus_file_get_location (file
);
3104 /* FIXME bugzilla.gnome.org 43020: This does sync. I/O and works only locally. */
3105 if (g_file_is_native (location
)) {
3106 target_uri
= nautilus_link_local_get_link_uri (uri
);
3107 if (target_uri
!= NULL
) {
3112 g_object_unref (location
);
3119 is_uri_relative (const char *uri
)
3123 scheme
= g_uri_parse_scheme (uri
);
3125 return scheme
== NULL
;
3129 get_custom_icon_metadata_uri (NautilusFile
*file
)
3131 char *custom_icon_uri
;
3135 uri
= nautilus_file_get_metadata (file
, NAUTILUS_METADATA_KEY_CUSTOM_ICON
, NULL
);
3137 nautilus_file_is_directory (file
) &&
3138 is_uri_relative (uri
)) {
3139 dir_uri
= nautilus_file_get_uri (file
);
3140 custom_icon_uri
= g_build_filename (dir_uri
, uri
, NULL
);
3144 custom_icon_uri
= uri
;
3146 return custom_icon_uri
;
3150 get_custom_icon (NautilusFile
*file
)
3152 char *custom_icon_uri
;
3162 /* Metadata takes precedence */
3163 custom_icon_uri
= get_custom_icon_metadata_uri (file
);
3165 if (custom_icon_uri
) {
3166 icon_file
= g_file_new_for_uri (custom_icon_uri
);
3167 icon
= g_file_icon_new (icon_file
);
3168 g_object_unref (icon_file
);
3171 if (icon
== NULL
&& file
->details
->got_link_info
&& file
->details
->custom_icon
!= NULL
) {
3172 if (g_path_is_absolute (file
->details
->custom_icon
)) {
3173 icon_file
= g_file_new_for_path (file
->details
->custom_icon
);
3174 icon
= g_file_icon_new (icon_file
);
3175 g_object_unref (icon_file
);
3177 icon
= g_themed_icon_new (file
->details
->custom_icon
);
3185 static int cached_thumbnail_limit
;
3186 static int cached_thumbnail_size
;
3187 static int show_image_thumbs
;
3189 GFilesystemPreviewType
3190 nautilus_file_get_filesystem_use_preview (NautilusFile
*file
)
3192 GFilesystemPreviewType use_preview
;
3193 NautilusFile
*parent
;
3195 parent
= nautilus_file_get_parent (file
);
3196 if (parent
!= NULL
) {
3197 use_preview
= parent
->details
->filesystem_use_preview
;
3198 g_object_unref (parent
);
3207 nautilus_file_should_show_thumbnail (NautilusFile
*file
)
3209 const char *mime_type
;
3210 GFilesystemPreviewType use_preview
;
3212 use_preview
= nautilus_file_get_filesystem_use_preview (file
);
3214 mime_type
= eel_ref_str_peek (file
->details
->mime_type
);
3215 if (mime_type
== NULL
) {
3216 mime_type
= "application/octet-stream";
3219 /* If the thumbnail has already been created, don't care about the size
3220 * of the original file.
3222 if (nautilus_thumbnail_is_mimetype_limited_by_size (mime_type
) &&
3223 file
->details
->thumbnail_path
== NULL
&&
3224 nautilus_file_get_size (file
) > (unsigned int)cached_thumbnail_limit
) {
3228 if (show_image_thumbs
== NAUTILUS_SPEED_TRADEOFF_ALWAYS
) {
3229 if (use_preview
== G_FILESYSTEM_PREVIEW_TYPE_NEVER
) {
3234 } else if (show_image_thumbs
== NAUTILUS_SPEED_TRADEOFF_NEVER
) {
3237 if (use_preview
== G_FILESYSTEM_PREVIEW_TYPE_NEVER
) {
3238 /* file system says to never thumbnail anything */
3240 } else if (use_preview
== G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL
) {
3241 /* file system says we should treat file as if it's local */
3244 /* only local files */
3245 return nautilus_file_is_local (file
);
3253 nautilus_file_get_gicon (NautilusFile
*file
,
3254 NautilusFileIconFlags flags
)
3256 const char * const * names
;
3267 if (file
->details
->icon
) {
3270 if (((flags
& NAUTILUS_FILE_ICON_FLAGS_EMBEDDING_TEXT
) ||
3271 (flags
& NAUTILUS_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT
) ||
3272 (flags
& NAUTILUS_FILE_ICON_FLAGS_FOR_OPEN_FOLDER
) ||
3273 ((flags
& NAUTILUS_FILE_ICON_FLAGS_IGNORE_VISITING
) == 0 &&
3274 nautilus_file_has_open_window (file
))) &&
3275 G_IS_THEMED_ICON (file
->details
->icon
)) {
3276 names
= g_themed_icon_get_names (G_THEMED_ICON (file
->details
->icon
));
3277 array
= g_ptr_array_new ();
3280 for (i
= 0; names
[i
] != NULL
; i
++) {
3283 if (strcmp (name
, "folder") == 0 &&
3284 (flags
& NAUTILUS_FILE_ICON_FLAGS_IGNORE_VISITING
) == 0 &&
3285 nautilus_file_has_open_window (file
)) {
3287 g_ptr_array_add (array
, "folder-visiting");
3289 if (strcmp (name
, "folder") == 0 &&
3290 (flags
& NAUTILUS_FILE_ICON_FLAGS_FOR_DRAG_ACCEPT
)) {
3292 g_ptr_array_add (array
, "folder-drag-accept");
3294 if (strcmp (name
, "folder") == 0 &&
3295 (flags
& NAUTILUS_FILE_ICON_FLAGS_FOR_OPEN_FOLDER
)) {
3297 g_ptr_array_add (array
, "folder-open");
3299 if (strcmp (name
, "text-x-generic") == 0 &&
3300 (flags
& NAUTILUS_FILE_ICON_FLAGS_EMBEDDING_TEXT
)) {
3302 g_ptr_array_add (array
, "text-x-preview");
3304 g_ptr_array_add (array
, (char *)name
);
3308 icon
= g_themed_icon_new_from_names ((char **)array
->pdata
, array
->len
);
3311 g_ptr_array_free (array
, TRUE
);
3315 icon
= g_object_ref (file
->details
->icon
);
3321 return g_themed_icon_new ("text-x-generic");
3325 nautilus_file_get_icon (NautilusFile
*file
,
3327 NautilusFileIconFlags flags
)
3329 NautilusIconInfo
*icon
;
3331 GdkPixbuf
*raw_pixbuf
, *scaled_pixbuf
;
3338 gicon
= get_custom_icon (file
);
3340 icon
= nautilus_icon_info_lookup (gicon
, size
);
3341 g_object_unref (gicon
);
3345 modified_size
= size
* cached_thumbnail_size
/ NAUTILUS_ICON_SIZE_STANDARD
;
3347 if (flags
& NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS
&&
3348 nautilus_file_should_show_thumbnail (file
)) {
3349 if (file
->details
->thumbnail
) {
3350 if (file
->details
->thumbnail_size
== modified_size
) {
3351 scaled_pixbuf
= g_object_ref (file
->details
->thumbnail
);
3356 if (file
->details
->thumbnail_size
== 0) {
3357 raw_pixbuf
= g_object_ref (file
->details
->thumbnail
);
3359 raw_pixbuf
= nautilus_thumbnail_unframe_image (file
->details
->thumbnail
);
3362 w
= gdk_pixbuf_get_width (raw_pixbuf
);
3363 h
= gdk_pixbuf_get_height (raw_pixbuf
);
3365 /* These compensates for frame size which will be added on the raw image */
3366 s
= MAX (NAUTILUS_THUMBNAIL_FRAME_LEFT
+ w
+ NAUTILUS_THUMBNAIL_FRAME_RIGHT
,
3367 NAUTILUS_THUMBNAIL_FRAME_TOP
+ h
+ NAUTILUS_THUMBNAIL_FRAME_BOTTOM
);
3369 scale
= (double)modified_size
/ s
;
3371 scaled_pixbuf
= gdk_pixbuf_scale_simple (raw_pixbuf
,
3372 w
* scale
, h
* scale
,
3374 nautilus_thumbnail_frame_image (&scaled_pixbuf
);
3376 g_object_unref (raw_pixbuf
);
3378 if (modified_size
> file
->details
->thumbnail_size
) {
3379 /* Invalidate if we resize upward (and the
3380 loaded was not the original raw version, w/ size 0).
3382 if (file
->details
->thumbnail_size
!= 0 ||
3383 (modified_size
> 128 && !file
->details
->thumbnail_tried_original
)) {
3384 nautilus_file_invalidate_attributes (file
, NAUTILUS_FILE_ATTRIBUTE_THUMBNAIL
);
3386 file
->details
->thumbnail_size
= modified_size
;
3387 g_object_unref (file
->details
->thumbnail
);
3388 file
->details
->thumbnail
= g_object_ref (scaled_pixbuf
);
3392 icon
= nautilus_icon_info_new_for_pixbuf (scaled_pixbuf
);
3393 g_object_unref (scaled_pixbuf
);
3395 } else if (file
->details
->thumbnail_path
== NULL
&&
3396 file
->details
->can_read
&&
3397 !file
->details
->thumbnailing_failed
&&
3398 !file
->details
->is_thumbnailing
) {
3399 if (nautilus_can_thumbnail (file
)) {
3400 nautilus_create_thumbnail (file
);
3405 if (file
->details
->is_thumbnailing
&&
3406 flags
& NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS
)
3407 gicon
= g_themed_icon_new (ICON_NAME_THUMBNAIL_LOADING
);
3409 gicon
= nautilus_file_get_gicon (file
, flags
);
3412 icon
= nautilus_icon_info_lookup (gicon
, size
);
3413 g_object_unref (gicon
);
3417 return nautilus_icon_info_new_for_pixbuf (NULL
);
3421 nautilus_file_get_icon_pixbuf (NautilusFile
*file
,
3423 gboolean force_size
,
3424 NautilusFileIconFlags flags
)
3426 NautilusIconInfo
*info
;
3429 info
= nautilus_file_get_icon (file
, size
, flags
);
3431 pixbuf
= nautilus_icon_info_get_pixbuf_at_size (info
, size
);
3433 pixbuf
= nautilus_icon_info_get_pixbuf (info
);
3435 g_object_unref (info
);
3441 nautilus_file_get_custom_icon (NautilusFile
*file
)
3449 /* Metadata takes precedence */
3450 custom_icon
= get_custom_icon_metadata_uri (file
);
3452 if (custom_icon
== NULL
&& file
->details
->got_link_info
) {
3453 custom_icon
= g_strdup (file
->details
->custom_icon
);
3461 nautilus_file_get_date (NautilusFile
*file
,
3462 NautilusDateType date_type
,
3469 g_return_val_if_fail (date_type
== NAUTILUS_DATE_TYPE_CHANGED
3470 || date_type
== NAUTILUS_DATE_TYPE_ACCESSED
3471 || date_type
== NAUTILUS_DATE_TYPE_MODIFIED
3472 || date_type
== NAUTILUS_DATE_TYPE_PERMISSIONS_CHANGED
, FALSE
);
3478 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
3480 return EEL_CALL_METHOD_WITH_RETURN_VALUE
3481 (NAUTILUS_FILE_CLASS
, file
,
3482 get_date
, (file
, date_type
, date
));
3486 nautilus_file_get_where_string (NautilusFile
*file
)
3492 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
3494 return EEL_CALL_METHOD_WITH_RETURN_VALUE
3495 (NAUTILUS_FILE_CLASS
, file
,
3496 get_where_string
, (file
));
3499 static const char *TODAY_TIME_FORMATS
[] = {
3500 /* Today, use special word.
3501 * strftime patterns preceeded with the widest
3502 * possible resulting string for that pattern.
3504 * Note to localizers: You can look at man strftime
3505 * for details on the format, but you should only use
3506 * the specifiers from the C standard, not extensions.
3507 * These include "%" followed by one of
3508 * "aAbBcdHIjmMpSUwWxXyYZ". There are two extensions
3509 * in the Nautilus version of strftime that can be
3510 * used (and match GNU extensions). Putting a "-"
3511 * between the "%" and any numeric directive will turn
3512 * off zero padding, and putting a "_" there will use
3513 * space padding instead of zero padding.
3515 N_("today at 00:00:00 PM"),
3516 N_("today at %-I:%M:%S %p"),
3518 N_("today at 00:00 PM"),
3519 N_("today at %-I:%M %p"),
3521 N_("today, 00:00 PM"),
3522 N_("today, %-I:%M %p"),
3530 static const char *YESTERDAY_TIME_FORMATS
[] = {
3531 /* Yesterday, use special word.
3532 * Note to localizers: Same issues as "today" string.
3534 N_("yesterday at 00:00:00 PM"),
3535 N_("yesterday at %-I:%M:%S %p"),
3537 N_("yesterday at 00:00 PM"),
3538 N_("yesterday at %-I:%M %p"),
3540 N_("yesterday, 00:00 PM"),
3541 N_("yesterday, %-I:%M %p"),
3549 static const char *CURRENT_WEEK_TIME_FORMATS
[] = {
3550 /* Current week, include day of week.
3551 * Note to localizers: Same issues as "today" string.
3552 * The width measurement templates correspond to
3553 * the day/month name with the most letters.
3555 N_("Wednesday, September 00 0000 at 00:00:00 PM"),
3556 N_("%A, %B %-d %Y at %-I:%M:%S %p"),
3558 N_("Mon, Oct 00 0000 at 00:00:00 PM"),
3559 N_("%a, %b %-d %Y at %-I:%M:%S %p"),
3561 N_("Mon, Oct 00 0000 at 00:00 PM"),
3562 N_("%a, %b %-d %Y at %-I:%M %p"),
3564 N_("Oct 00 0000 at 00:00 PM"),
3565 N_("%b %-d %Y at %-I:%M %p"),
3567 N_("Oct 00 0000, 00:00 PM"),
3568 N_("%b %-d %Y, %-I:%M %p"),
3570 N_("00/00/00, 00:00 PM"),
3571 N_("%m/%-d/%y, %-I:%M %p"),
3580 nautilus_file_fit_date_as_string (NautilusFile
*file
,
3581 NautilusDateType date_type
,
3583 NautilusWidthMeasureCallback measure_callback
,
3584 NautilusTruncateCallback truncate_callback
,
3585 void *measure_context
)
3587 time_t file_time_raw
;
3588 struct tm
*file_time
;
3589 const char **formats
;
3590 const char *width_template
;
3596 guint32 file_date_age
;
3599 if (!nautilus_file_get_date (file
, date_type
, &file_time_raw
)) {
3603 file_time
= localtime (&file_time_raw
);
3605 if (date_format_pref
== NAUTILUS_DATE_FORMAT_LOCALE
) {
3606 return eel_strdup_strftime ("%c", file_time
);
3607 } else if (date_format_pref
== NAUTILUS_DATE_FORMAT_ISO
) {
3608 return eel_strdup_strftime ("%Y-%m-%d %H:%M:%S", file_time
);
3611 file_date
= eel_g_date_new_tm (file_time
);
3613 today
= g_date_new ();
3614 g_date_set_time_t (today
, time (NULL
));
3616 /* Overflow results in a large number; fine for our purposes. */
3617 file_date_age
= (g_date_get_julian (today
) -
3618 g_date_get_julian (file_date
));
3620 g_date_free (file_date
);
3621 g_date_free (today
);
3623 /* Format varies depending on how old the date is. This minimizes
3624 * the length (and thus clutter & complication) of typical dates
3625 * while providing sufficient detail for recent dates to make
3626 * them maximally understandable at a glance. Keep all format
3627 * strings separate rather than combining bits & pieces for
3628 * internationalization's sake.
3631 if (file_date_age
== 0) {
3632 formats
= TODAY_TIME_FORMATS
;
3633 } else if (file_date_age
== 1) {
3634 formats
= YESTERDAY_TIME_FORMATS
;
3635 } else if (file_date_age
< 7) {
3636 formats
= CURRENT_WEEK_TIME_FORMATS
;
3638 formats
= CURRENT_WEEK_TIME_FORMATS
;
3641 /* Find the date format that just fits the required width. Instead of measuring
3642 * the resulting string width directly, measure the width of a template that represents
3643 * the widest possible version of a date in a given format. This is done by using M, m
3644 * and 0 for the variable letters/digits respectively.
3648 for (i
= 0; ; i
+= 2) {
3649 width_template
= (formats
[i
] ? _(formats
[i
]) : NULL
);
3650 if (width_template
== NULL
) {
3651 /* no more formats left */
3652 g_assert (format
!= NULL
);
3654 /* Can't fit even the shortest format -- return an ellipsized form in the
3658 date_string
= eel_strdup_strftime (format
, file_time
);
3660 if (truncate_callback
== NULL
) {
3664 result
= (* truncate_callback
) (date_string
, width
, measure_context
);
3665 g_free (date_string
);
3669 format
= _(formats
[i
+ 1]);
3671 if (measure_callback
== NULL
) {
3672 /* don't care about fitting the width */
3676 if ((* measure_callback
) (width_template
, measure_context
) <= width
) {
3677 /* The template fits, this is the format we can fit. */
3682 return eel_strdup_strftime (format
, file_time
);
3687 * nautilus_file_fit_modified_date_as_string:
3689 * Get a user-displayable string representing a file modification date,
3690 * truncated to @width using the measuring and truncating callbacks.
3691 * @file: NautilusFile representing the file in question.
3692 * @width: The desired resulting string width.
3693 * @measure_callback: The callback used to measure the string width.
3694 * @truncate_callback: The callback used to truncate the string to a desired width.
3695 * @measure_context: Data neede when measuring and truncating.
3697 * Returns: Newly allocated string ready to display to the user.
3701 nautilus_file_fit_modified_date_as_string (NautilusFile
*file
,
3703 NautilusWidthMeasureCallback measure_callback
,
3704 NautilusTruncateCallback truncate_callback
,
3705 void *measure_context
)
3707 return nautilus_file_fit_date_as_string (file
, NAUTILUS_DATE_TYPE_MODIFIED
,
3708 width
, measure_callback
, truncate_callback
, measure_context
);
3712 * nautilus_file_get_date_as_string:
3714 * Get a user-displayable string representing a file modification date.
3715 * The caller is responsible for g_free-ing this string.
3716 * @file: NautilusFile representing the file in question.
3718 * Returns: Newly allocated string ready to display to the user.
3722 nautilus_file_get_date_as_string (NautilusFile
*file
, NautilusDateType date_type
)
3724 return nautilus_file_fit_date_as_string (file
, date_type
,
3725 0, NULL
, NULL
, NULL
);
3728 static NautilusSpeedTradeoffValue show_directory_item_count
;
3729 static NautilusSpeedTradeoffValue show_text_in_icons
;
3732 show_text_in_icons_changed_callback (gpointer callback_data
)
3734 show_text_in_icons
= eel_preferences_get_enum (NAUTILUS_PREFERENCES_SHOW_TEXT_IN_ICONS
);
3738 show_directory_item_count_changed_callback (gpointer callback_data
)
3740 show_directory_item_count
= eel_preferences_get_enum (NAUTILUS_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS
);
3744 get_speed_tradeoff_preference_for_file (NautilusFile
*file
, NautilusSpeedTradeoffValue value
)
3746 GFilesystemPreviewType use_preview
;
3748 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
3750 use_preview
= nautilus_file_get_filesystem_use_preview (file
);
3752 if (value
== NAUTILUS_SPEED_TRADEOFF_ALWAYS
) {
3753 if (use_preview
== G_FILESYSTEM_PREVIEW_TYPE_NEVER
) {
3760 if (value
== NAUTILUS_SPEED_TRADEOFF_NEVER
) {
3764 g_assert (value
== NAUTILUS_SPEED_TRADEOFF_LOCAL_ONLY
);
3766 if (use_preview
== G_FILESYSTEM_PREVIEW_TYPE_NEVER
) {
3767 /* file system says to never preview anything */
3769 } else if (use_preview
== G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL
) {
3770 /* file system says we should treat file as if it's local */
3773 /* only local files */
3774 return nautilus_file_is_local (file
);
3779 nautilus_file_should_show_directory_item_count (NautilusFile
*file
)
3781 static gboolean show_directory_item_count_callback_added
= FALSE
;
3783 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
3785 if (file
->details
->mime_type
&&
3786 strcmp (eel_ref_str_peek (file
->details
->mime_type
), "x-directory/smb-share") == 0) {
3790 /* Add the callback once for the life of our process */
3791 if (!show_directory_item_count_callback_added
) {
3792 eel_preferences_add_callback (NAUTILUS_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS
,
3793 show_directory_item_count_changed_callback
,
3795 show_directory_item_count_callback_added
= TRUE
;
3797 /* Peek for the first time */
3798 show_directory_item_count_changed_callback (NULL
);
3801 return get_speed_tradeoff_preference_for_file (file
, show_directory_item_count
);
3805 nautilus_file_should_show_type (NautilusFile
*file
)
3810 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
3812 uri
= nautilus_file_get_uri (file
);
3813 ret
= ((strcmp (uri
, "computer:///") != 0) &&
3814 (strcmp (uri
, "network:///") != 0) &&
3815 (strcmp (uri
, "smb:///") != 0));
3822 nautilus_file_should_get_top_left_text (NautilusFile
*file
)
3824 static gboolean show_text_in_icons_callback_added
= FALSE
;
3826 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
3828 /* Add the callback once for the life of our process */
3829 if (!show_text_in_icons_callback_added
) {
3830 eel_preferences_add_callback (NAUTILUS_PREFERENCES_SHOW_TEXT_IN_ICONS
,
3831 show_text_in_icons_changed_callback
,
3833 show_text_in_icons_callback_added
= TRUE
;
3835 /* Peek for the first time */
3836 show_text_in_icons_changed_callback (NULL
);
3839 if (show_text_in_icons
== NAUTILUS_SPEED_TRADEOFF_ALWAYS
) {
3843 if (show_text_in_icons
== NAUTILUS_SPEED_TRADEOFF_NEVER
) {
3847 return get_speed_tradeoff_preference_for_file (file
, show_text_in_icons
);
3851 * nautilus_file_get_directory_item_count
3853 * Get the number of items in a directory.
3854 * @file: NautilusFile representing a directory.
3855 * @count: Place to put count.
3856 * @count_unreadable: Set to TRUE (if non-NULL) if permissions prevent
3857 * the item count from being read on this directory. Otherwise set to FALSE.
3859 * Returns: TRUE if count is available.
3863 nautilus_file_get_directory_item_count (NautilusFile
*file
,
3865 gboolean
*count_unreadable
)
3867 if (count
!= NULL
) {
3870 if (count_unreadable
!= NULL
) {
3871 *count_unreadable
= FALSE
;
3874 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
3876 if (!nautilus_file_is_directory (file
)) {
3880 if (!nautilus_file_should_show_directory_item_count (file
)) {
3884 return EEL_CALL_METHOD_WITH_RETURN_VALUE
3885 (NAUTILUS_FILE_CLASS
, file
,
3886 get_item_count
, (file
, count
, count_unreadable
));
3890 * nautilus_file_get_deep_counts
3892 * Get the statistics about items inside a directory.
3893 * @file: NautilusFile representing a directory or file.
3894 * @directory_count: Place to put count of directories inside.
3895 * @files_count: Place to put count of files inside.
3896 * @unreadable_directory_count: Number of directories encountered
3897 * that were unreadable.
3898 * @total_size: Total size of all files and directories visited.
3899 * @force: Whether the deep counts should even be collected if
3900 * nautilus_file_should_show_directory_item_count returns FALSE
3903 * Returns: Status to indicate whether sizes are available.
3906 NautilusRequestStatus
3907 nautilus_file_get_deep_counts (NautilusFile
*file
,
3908 guint
*directory_count
,
3910 guint
*unreadable_directory_count
,
3911 goffset
*total_size
,
3914 if (directory_count
!= NULL
) {
3915 *directory_count
= 0;
3917 if (file_count
!= NULL
) {
3920 if (unreadable_directory_count
!= NULL
) {
3921 *unreadable_directory_count
= 0;
3923 if (total_size
!= NULL
) {
3927 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NAUTILUS_REQUEST_DONE
);
3929 if (!force
&& !nautilus_file_should_show_directory_item_count (file
)) {
3930 /* Set field so an existing value isn't treated as up-to-date
3931 * when preference changes later.
3933 file
->details
->deep_counts_status
= NAUTILUS_REQUEST_NOT_STARTED
;
3934 return file
->details
->deep_counts_status
;
3937 return EEL_CALL_METHOD_WITH_RETURN_VALUE
3938 (NAUTILUS_FILE_CLASS
, file
,
3939 get_deep_counts
, (file
,
3942 unreadable_directory_count
,
3947 nautilus_file_recompute_deep_counts (NautilusFile
*file
)
3949 if (file
->details
->deep_counts_status
!= NAUTILUS_REQUEST_IN_PROGRESS
) {
3950 file
->details
->deep_counts_status
= NAUTILUS_REQUEST_NOT_STARTED
;
3951 if (file
->details
->directory
!= NULL
) {
3952 nautilus_directory_add_file_to_work_queue (file
->details
->directory
, file
);
3953 nautilus_directory_async_state_changed (file
->details
->directory
);
3960 * nautilus_file_get_directory_item_mime_types
3962 * Get the list of mime-types present in a directory.
3963 * @file: NautilusFile representing a directory. It is an error to
3964 * call this function on a file that is not a directory.
3965 * @mime_list: Place to put the list of mime-types.
3967 * Returns: TRUE if mime-type list is available.
3971 nautilus_file_get_directory_item_mime_types (NautilusFile
*file
,
3974 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
3975 g_return_val_if_fail (mime_list
!= NULL
, FALSE
);
3977 if (!nautilus_file_is_directory (file
)
3978 || !file
->details
->got_mime_list
) {
3983 *mime_list
= eel_g_str_list_copy (file
->details
->mime_list
);
3988 nautilus_file_can_get_size (NautilusFile
*file
)
3990 return file
->details
->size
== -1;
3995 * nautilus_file_get_size
3997 * Get the file size.
3998 * @file: NautilusFile representing the file in question.
4000 * Returns: Size in bytes.
4004 nautilus_file_get_size (NautilusFile
*file
)
4006 /* Before we have info on the file, we don't know the size. */
4007 if (file
->details
->size
== -1)
4009 return file
->details
->size
;
4013 nautilus_file_get_mtime (NautilusFile
*file
)
4015 return file
->details
->mtime
;
4020 set_attributes_get_info_callback (GObject
*source_object
,
4022 gpointer callback_data
)
4024 NautilusFileOperation
*op
;
4025 GFileInfo
*new_info
;
4031 new_info
= g_file_query_info_finish (G_FILE (source_object
), res
, &error
);
4032 if (new_info
!= NULL
) {
4033 nautilus_file_update_info (op
->file
, new_info
);
4034 g_object_unref (new_info
);
4036 nautilus_file_operation_complete (op
, NULL
, error
);
4038 g_error_free (error
);
4044 set_attributes_callback (GObject
*source_object
,
4045 GAsyncResult
*result
,
4046 gpointer callback_data
)
4048 NautilusFileOperation
*op
;
4055 res
= g_file_set_attributes_finish (G_FILE (source_object
),
4061 g_file_query_info_async (G_FILE (source_object
),
4062 NAUTILUS_FILE_DEFAULT_ATTRIBUTES
,
4066 set_attributes_get_info_callback
, op
);
4068 nautilus_file_operation_complete (op
, NULL
, error
);
4069 g_error_free (error
);
4074 nautilus_file_set_attributes (NautilusFile
*file
,
4075 GFileInfo
*attributes
,
4076 NautilusFileOperationCallback callback
,
4077 gpointer callback_data
)
4079 NautilusFileOperation
*op
;
4082 op
= nautilus_file_operation_new (file
, callback
, callback_data
);
4084 location
= nautilus_file_get_location (file
);
4085 g_file_set_attributes_async (location
,
4090 set_attributes_callback
,
4092 g_object_unref (location
);
4097 * nautilus_file_can_get_permissions:
4099 * Check whether the permissions for a file are determinable.
4100 * This might not be the case for files on non-UNIX file systems.
4102 * @file: The file in question.
4104 * Return value: TRUE if the permissions are valid.
4107 nautilus_file_can_get_permissions (NautilusFile
*file
)
4109 return file
->details
->has_permissions
;
4113 * nautilus_file_can_set_permissions:
4115 * Check whether the current user is allowed to change
4116 * the permissions of a file.
4118 * @file: The file in question.
4120 * Return value: TRUE if the current user can change the
4121 * permissions of @file, FALSE otherwise. It's always possible
4122 * that when you actually try to do it, you will fail.
4125 nautilus_file_can_set_permissions (NautilusFile
*file
)
4129 if (file
->details
->uid
!= -1 &&
4130 nautilus_file_is_local (file
)) {
4131 /* Check the user. */
4132 user_id
= geteuid();
4134 /* Owner is allowed to set permissions. */
4135 if (user_id
== (uid_t
) file
->details
->uid
) {
4139 /* Root is also allowed to set permissions. */
4144 /* Nobody else is allowed. */
4148 /* pretend to have full chmod rights when no info is available, relevant when
4149 * the FS can't provide ownership info, for instance for FTP */
4154 nautilus_file_get_permissions (NautilusFile
*file
)
4156 g_return_val_if_fail (nautilus_file_can_get_permissions (file
), 0);
4158 return file
->details
->permissions
;
4162 * nautilus_file_set_permissions:
4164 * Change a file's permissions. This should only be called if
4165 * nautilus_file_can_set_permissions returned TRUE.
4167 * @file: NautilusFile representing the file in question.
4168 * @new_permissions: New permissions value. This is the whole
4169 * set of permissions, not a delta.
4172 nautilus_file_set_permissions (NautilusFile
*file
,
4173 guint32 new_permissions
,
4174 NautilusFileOperationCallback callback
,
4175 gpointer callback_data
)
4180 if (!nautilus_file_can_set_permissions (file
)) {
4181 /* Claim that something changed even if the permission change failed.
4182 * This makes it easier for some clients who see the "reverting"
4183 * to the old permissions as "changing back".
4185 nautilus_file_changed (file
);
4186 error
= g_error_new (G_IO_ERROR
, G_IO_ERROR_PERMISSION_DENIED
,
4187 _("Not allowed to set permissions"));
4188 (* callback
) (file
, NULL
, error
, callback_data
);
4189 g_error_free (error
);
4193 /* Test the permissions-haven't-changed case explicitly
4194 * because we don't want to send the file-changed signal if
4197 if (new_permissions
== file
->details
->permissions
) {
4198 (* callback
) (file
, NULL
, NULL
, callback_data
);
4202 info
= g_file_info_new ();
4203 g_file_info_set_attribute_uint32 (info
, G_FILE_ATTRIBUTE_UNIX_MODE
, new_permissions
);
4204 nautilus_file_set_attributes (file
, info
, callback
, callback_data
);
4205 g_object_unref (info
);
4209 * nautilus_file_can_get_selinux_context:
4211 * Check whether the selinux context for a file are determinable.
4212 * This might not be the case for files on non-UNIX file systems,
4213 * files without a context or systems that don't support selinux.
4215 * @file: The file in question.
4217 * Return value: TRUE if the permissions are valid.
4220 nautilus_file_can_get_selinux_context (NautilusFile
*file
)
4222 return file
->details
->selinux_context
!= NULL
;
4227 * nautilus_file_get_selinux_context:
4229 * Get a user-displayable string representing a file's selinux
4231 * @file: NautilusFile representing the file in question.
4233 * Returns: Newly allocated string ready to display to the user.
4237 nautilus_file_get_selinux_context (NautilusFile
*file
)
4242 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
4244 if (!nautilus_file_can_get_selinux_context (file
)) {
4248 raw
= file
->details
->selinux_context
;
4251 if (selinux_raw_to_trans_context (raw
, &translated
) == 0) {
4253 tmp
= g_strdup (translated
);
4254 freecon (translated
);
4260 translated
= g_strdup (raw
);
4267 get_real_name (const char *name
, const char *gecos
)
4269 char *locale_string
, *part_before_comma
, *capitalized_login_name
, *real_name
;
4271 if (gecos
== NULL
) {
4275 locale_string
= eel_str_strip_substring_and_after (gecos
, ",");
4276 if (!g_utf8_validate (locale_string
, -1, NULL
)) {
4277 part_before_comma
= g_locale_to_utf8 (locale_string
, -1, NULL
, NULL
, NULL
);
4278 g_free (locale_string
);
4280 part_before_comma
= locale_string
;
4283 if (!g_utf8_validate (name
, -1, NULL
)) {
4284 locale_string
= g_locale_to_utf8 (name
, -1, NULL
, NULL
, NULL
);
4286 locale_string
= g_strdup (name
);
4289 capitalized_login_name
= eel_str_capitalize (locale_string
);
4290 g_free (locale_string
);
4292 if (capitalized_login_name
== NULL
) {
4293 real_name
= part_before_comma
;
4295 real_name
= eel_str_replace_substring
4296 (part_before_comma
, "&", capitalized_login_name
);
4297 g_free (part_before_comma
);
4301 if (eel_str_is_empty (real_name
)
4302 || eel_strcmp (name
, real_name
) == 0
4303 || eel_strcmp (capitalized_login_name
, real_name
) == 0) {
4308 g_free (capitalized_login_name
);
4314 get_user_and_real_name_from_id (uid_t uid
)
4317 char *real_name
, *user_and_real_name
;
4319 name
= nautilus_users_cache_get_name (uid
);
4320 gecos
= nautilus_users_cache_get_gecos (uid
);
4322 real_name
= get_real_name (name
, gecos
);
4323 if (real_name
!= NULL
) {
4324 user_and_real_name
= g_strdup_printf ("%s - %s", name
, real_name
);
4326 user_and_real_name
= g_strdup (name
);
4333 return user_and_real_name
;
4337 get_group_id_from_group_name (const char *group_name
, uid_t
*gid
)
4339 struct group
*group
;
4341 g_assert (gid
!= NULL
);
4343 group
= getgrnam (group_name
);
4345 if (group
== NULL
) {
4349 *gid
= group
->gr_gid
;
4355 get_ids_from_user_name (const char *user_name
, uid_t
*uid
, uid_t
*gid
)
4357 struct passwd
*password_info
;
4359 g_assert (uid
!= NULL
|| gid
!= NULL
);
4361 password_info
= getpwnam (user_name
);
4363 if (password_info
== NULL
) {
4368 *uid
= password_info
->pw_uid
;
4372 *gid
= password_info
->pw_gid
;
4379 get_user_id_from_user_name (const char *user_name
, uid_t
*id
)
4381 return get_ids_from_user_name (user_name
, id
, NULL
);
4385 get_id_from_digit_string (const char *digit_string
, uid_t
*id
)
4390 g_assert (id
!= NULL
);
4392 /* Only accept string if it has one integer with nothing
4395 if (sscanf (digit_string
, "%ld%c", &scanned_id
, &c
) != 1) {
4403 * nautilus_file_can_get_owner:
4405 * Check whether the owner a file is determinable.
4406 * This might not be the case for files on non-UNIX file systems.
4408 * @file: The file in question.
4410 * Return value: TRUE if the owner is valid.
4413 nautilus_file_can_get_owner (NautilusFile
*file
)
4415 /* Before we have info on a file, the owner is unknown. */
4416 return file
->details
->uid
!= -1;
4420 * nautilus_file_get_owner_name:
4422 * Get the user name of the file's owner. If the owner has no
4423 * name, returns the userid as a string. The caller is responsible
4424 * for g_free-ing this string.
4426 * @file: The file in question.
4428 * Return value: A newly-allocated string.
4431 nautilus_file_get_owner_name (NautilusFile
*file
)
4433 return nautilus_file_get_owner_as_string (file
, FALSE
);
4437 * nautilus_file_can_set_owner:
4439 * Check whether the current user is allowed to change
4440 * the owner of a file.
4442 * @file: The file in question.
4444 * Return value: TRUE if the current user can change the
4445 * owner of @file, FALSE otherwise. It's always possible
4446 * that when you actually try to do it, you will fail.
4449 nautilus_file_can_set_owner (NautilusFile
*file
)
4451 /* Not allowed to set the owner if we can't
4452 * even read it. This can happen on non-UNIX file
4455 if (!nautilus_file_can_get_owner (file
)) {
4459 /* Only root is also allowed to set the owner. */
4460 return geteuid() == 0;
4464 * nautilus_file_set_owner:
4466 * Set the owner of a file. This will only have any effect if
4467 * nautilus_file_can_set_owner returns TRUE.
4469 * @file: The file in question.
4470 * @user_name_or_id: The user name to set the owner to.
4471 * If the string does not match any user name, and the
4472 * string is an integer, the owner will be set to the
4473 * userid represented by that integer.
4474 * @callback: Function called when asynch owner change succeeds or fails.
4475 * @callback_data: Parameter passed back with callback function.
4478 nautilus_file_set_owner (NautilusFile
*file
,
4479 const char *user_name_or_id
,
4480 NautilusFileOperationCallback callback
,
4481 gpointer callback_data
)
4487 if (!nautilus_file_can_set_owner (file
)) {
4488 /* Claim that something changed even if the permission
4489 * change failed. This makes it easier for some
4490 * clients who see the "reverting" to the old owner as
4493 nautilus_file_changed (file
);
4494 error
= g_error_new (G_IO_ERROR
, G_IO_ERROR_PERMISSION_DENIED
,
4495 _("Not allowed to set owner"));
4496 (* callback
) (file
, NULL
, error
, callback_data
);
4497 g_error_free (error
);
4501 /* If no match treating user_name_or_id as name, try treating
4504 if (!get_user_id_from_user_name (user_name_or_id
, &new_id
)
4505 && !get_id_from_digit_string (user_name_or_id
, &new_id
)) {
4506 /* Claim that something changed even if the permission
4507 * change failed. This makes it easier for some
4508 * clients who see the "reverting" to the old owner as
4511 nautilus_file_changed (file
);
4512 error
= g_error_new (G_IO_ERROR
, G_IO_ERROR_INVALID_ARGUMENT
,
4513 _("Specified owner '%s' doesn't exist"), user_name_or_id
);
4514 (* callback
) (file
, NULL
, error
, callback_data
);
4515 g_error_free (error
);
4519 /* Test the owner-hasn't-changed case explicitly because we
4520 * don't want to send the file-changed signal if nothing
4523 if (new_id
== (uid_t
) file
->details
->uid
) {
4524 (* callback
) (file
, NULL
, NULL
, callback_data
);
4528 info
= g_file_info_new ();
4529 g_file_info_set_attribute_uint32 (info
, G_FILE_ATTRIBUTE_UNIX_UID
, new_id
);
4530 nautilus_file_set_attributes (file
, info
, callback
, callback_data
);
4531 g_object_unref (info
);
4535 * nautilus_get_user_names:
4537 * Get a list of user names. For users with a different associated
4538 * "real name", the real name follows the standard user name, separated
4539 * by a carriage return. The caller is responsible for freeing this list
4543 nautilus_get_user_names (void)
4546 char *real_name
, *name
;
4547 struct passwd
*user
;
4553 while ((user
= getpwent ()) != NULL
) {
4554 real_name
= get_real_name (user
->pw_name
, user
->pw_gecos
);
4555 if (real_name
!= NULL
) {
4556 name
= g_strconcat (user
->pw_name
, "\n", real_name
, NULL
);
4558 name
= g_strdup (user
->pw_name
);
4561 list
= g_list_prepend (list
, name
);
4566 return eel_g_str_list_alphabetize (list
);
4570 * nautilus_file_can_get_group:
4572 * Check whether the group a file is determinable.
4573 * This might not be the case for files on non-UNIX file systems.
4575 * @file: The file in question.
4577 * Return value: TRUE if the group is valid.
4580 nautilus_file_can_get_group (NautilusFile
*file
)
4582 /* Before we have info on a file, the group is unknown. */
4583 return file
->details
->gid
!= -1;
4587 * nautilus_file_get_group_name:
4589 * Get the name of the file's group. If the group has no
4590 * name, returns the groupid as a string. The caller is responsible
4591 * for g_free-ing this string.
4593 * @file: The file in question.
4595 * Return value: A newly-allocated string.
4598 nautilus_file_get_group_name (NautilusFile
*file
)
4602 /* Before we have info on a file, the owner is unknown. */
4603 if (file
->details
->gid
== -1) {
4607 group_name
= nautilus_groups_cache_get_name ((gid_t
) file
->details
->gid
);
4608 if (group_name
== NULL
) {
4609 /* In the oddball case that the group name has been set to an id for which
4610 * there is no defined group, return the id in string form.
4612 group_name
= g_strdup_printf ("%d", file
->details
->gid
);
4619 * nautilus_file_can_set_group:
4621 * Check whether the current user is allowed to change
4622 * the group of a file.
4624 * @file: The file in question.
4626 * Return value: TRUE if the current user can change the
4627 * group of @file, FALSE otherwise. It's always possible
4628 * that when you actually try to do it, you will fail.
4631 nautilus_file_can_set_group (NautilusFile
*file
)
4635 /* Not allowed to set the permissions if we can't
4636 * even read them. This can happen on non-UNIX file
4639 if (!nautilus_file_can_get_group (file
)) {
4643 /* Check the user. */
4644 user_id
= geteuid();
4646 /* Owner is allowed to set group (with restrictions). */
4647 if (user_id
== (uid_t
) file
->details
->uid
) {
4651 /* Root is also allowed to set group. */
4656 /* Nobody else is allowed. */
4660 /* Get a list of group names, filtered to only the ones
4661 * that contain the given username. If the username is
4662 * NULL, returns a list of all group names.
4665 nautilus_get_group_names_for_user (void)
4668 struct group
*group
;
4670 gid_t gid_list
[NGROUPS_MAX
+ 1];
4675 count
= getgroups (NGROUPS_MAX
+ 1, gid_list
);
4676 for (i
= 0; i
< count
; i
++) {
4677 group
= getgrgid (gid_list
[i
]);
4681 list
= g_list_prepend (list
, g_strdup (group
->gr_name
));
4684 return eel_g_str_list_alphabetize (list
);
4688 * nautilus_get_group_names:
4690 * Get a list of all group names.
4693 nautilus_get_all_group_names (void)
4696 struct group
*group
;
4702 while ((group
= getgrent ()) != NULL
)
4703 list
= g_list_prepend (list
, g_strdup (group
->gr_name
));
4707 return eel_g_str_list_alphabetize (list
);
4711 * nautilus_file_get_settable_group_names:
4713 * Get a list of all group names that the current user
4714 * can set the group of a specific file to.
4716 * @file: The NautilusFile in question.
4719 nautilus_file_get_settable_group_names (NautilusFile
*file
)
4724 if (!nautilus_file_can_set_group (file
)) {
4728 /* Check the user. */
4729 user_id
= geteuid();
4732 /* Root is allowed to set group to anything. */
4733 result
= nautilus_get_all_group_names ();
4734 } else if (user_id
== (uid_t
) file
->details
->uid
) {
4735 /* Owner is allowed to set group to any that owner is member of. */
4736 result
= nautilus_get_group_names_for_user ();
4738 g_warning ("unhandled case in nautilus_get_settable_group_names");
4746 * nautilus_file_set_group:
4748 * Set the group of a file. This will only have any effect if
4749 * nautilus_file_can_set_group returns TRUE.
4751 * @file: The file in question.
4752 * @group_name_or_id: The group name to set the owner to.
4753 * If the string does not match any group name, and the
4754 * string is an integer, the group will be set to the
4755 * group id represented by that integer.
4756 * @callback: Function called when asynch group change succeeds or fails.
4757 * @callback_data: Parameter passed back with callback function.
4760 nautilus_file_set_group (NautilusFile
*file
,
4761 const char *group_name_or_id
,
4762 NautilusFileOperationCallback callback
,
4763 gpointer callback_data
)
4769 if (!nautilus_file_can_set_group (file
)) {
4770 /* Claim that something changed even if the group
4771 * change failed. This makes it easier for some
4772 * clients who see the "reverting" to the old group as
4775 nautilus_file_changed (file
);
4776 error
= g_error_new (G_IO_ERROR
, G_IO_ERROR_PERMISSION_DENIED
,
4777 _("Not allowed to set group"));
4778 (* callback
) (file
, NULL
, error
, callback_data
);
4779 g_error_free (error
);
4783 /* If no match treating group_name_or_id as name, try treating
4786 if (!get_group_id_from_group_name (group_name_or_id
, &new_id
)
4787 && !get_id_from_digit_string (group_name_or_id
, &new_id
)) {
4788 /* Claim that something changed even if the group
4789 * change failed. This makes it easier for some
4790 * clients who see the "reverting" to the old group as
4793 nautilus_file_changed (file
);
4794 error
= g_error_new (G_IO_ERROR
, G_IO_ERROR_INVALID_ARGUMENT
,
4795 _("Specified group '%s' doesn't exist"), group_name_or_id
);
4796 (* callback
) (file
, NULL
, error
, callback_data
);
4797 g_error_free (error
);
4801 if (new_id
== (gid_t
) file
->details
->gid
) {
4802 (* callback
) (file
, NULL
, NULL
, callback_data
);
4807 info
= g_file_info_new ();
4808 g_file_info_set_attribute_uint32 (info
, G_FILE_ATTRIBUTE_UNIX_GID
, new_id
);
4809 nautilus_file_set_attributes (file
, info
, callback
, callback_data
);
4810 g_object_unref (info
);
4814 * nautilus_file_get_octal_permissions_as_string:
4816 * Get a user-displayable string representing a file's permissions
4817 * as an octal number. The caller
4818 * is responsible for g_free-ing this string.
4819 * @file: NautilusFile representing the file in question.
4821 * Returns: Newly allocated string ready to display to the user.
4825 nautilus_file_get_octal_permissions_as_string (NautilusFile
*file
)
4827 guint32 permissions
;
4829 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
4831 if (!nautilus_file_can_get_permissions (file
)) {
4835 permissions
= file
->details
->permissions
;
4836 return g_strdup_printf ("%03o", permissions
);
4840 * nautilus_file_get_permissions_as_string:
4842 * Get a user-displayable string representing a file's permissions. The caller
4843 * is responsible for g_free-ing this string.
4844 * @file: NautilusFile representing the file in question.
4846 * Returns: Newly allocated string ready to display to the user.
4850 nautilus_file_get_permissions_as_string (NautilusFile
*file
)
4852 guint32 permissions
;
4853 gboolean is_directory
;
4855 gboolean suid
, sgid
, sticky
;
4857 if (!nautilus_file_can_get_permissions (file
)) {
4861 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
4863 permissions
= file
->details
->permissions
;
4864 is_directory
= nautilus_file_is_directory (file
);
4865 is_link
= nautilus_file_is_symbolic_link (file
);
4867 /* We use ls conventions for displaying these three obscure flags */
4868 suid
= permissions
& S_ISGID
;
4869 sgid
= permissions
& S_ISGID
;
4870 sticky
= permissions
& S_ISVTX
;
4872 return g_strdup_printf ("%c%c%c%c%c%c%c%c%c%c",
4873 is_link
? 'l' : is_directory
? 'd' : '-',
4874 permissions
& S_IRUSR
? 'r' : '-',
4875 permissions
& S_IWUSR
? 'w' : '-',
4876 permissions
& S_IXUSR
4877 ? (suid
? 's' : 'x')
4878 : (suid
? 'S' : '-'),
4879 permissions
& S_IRGRP
? 'r' : '-',
4880 permissions
& S_IWGRP
? 'w' : '-',
4881 permissions
& S_IXGRP
4882 ? (sgid
? 's' : 'x')
4883 : (sgid
? 'S' : '-'),
4884 permissions
& S_IROTH
? 'r' : '-',
4885 permissions
& S_IWOTH
? 'w' : '-',
4886 permissions
& S_IXOTH
4887 ? (sticky
? 't' : 'x')
4888 : (sticky
? 'T' : '-'));
4892 * nautilus_file_get_owner_as_string:
4894 * Get a user-displayable string representing a file's owner. The caller
4895 * is responsible for g_free-ing this string.
4896 * @file: NautilusFile representing the file in question.
4897 * @include_real_name: Whether or not to append the real name (if any)
4898 * for this user after the user name.
4900 * Returns: Newly allocated string ready to display to the user.
4904 nautilus_file_get_owner_as_string (NautilusFile
*file
, gboolean include_real_name
)
4908 /* Before we have info on a file, the owner is unknown. */
4909 if (file
->details
->uid
== -1) {
4913 if (include_real_name
) {
4914 user_name
= get_user_and_real_name_from_id (file
->details
->uid
);
4916 user_name
= nautilus_users_cache_get_name (file
->details
->uid
);
4919 if (user_name
== NULL
) {
4920 /* In the oddball case that the user name has been set to an id for which
4921 * there is no defined user, return the id in string form.
4923 user_name
= g_strdup_printf ("%d", file
->details
->uid
);
4930 format_item_count_for_display (guint item_count
,
4931 gboolean includes_directories
,
4932 gboolean includes_files
)
4934 g_return_val_if_fail (includes_directories
|| includes_files
, NULL
);
4936 return g_strdup_printf (includes_directories
4938 ? ngettext ("%'u item", "%'u items", item_count
)
4939 : ngettext ("%'u folder", "%'u folders", item_count
))
4940 : ngettext ("%'u file", "%'u files", item_count
), item_count
);
4944 * nautilus_file_get_size_as_string:
4946 * Get a user-displayable string representing a file size. The caller
4947 * is responsible for g_free-ing this string. The string is an item
4948 * count for directories.
4949 * @file: NautilusFile representing the file in question.
4951 * Returns: Newly allocated string ready to display to the user.
4955 nautilus_file_get_size_as_string (NautilusFile
*file
)
4958 gboolean count_unreadable
;
4964 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
4966 if (nautilus_file_is_directory (file
)) {
4967 if (!nautilus_file_get_directory_item_count (file
, &item_count
, &count_unreadable
)) {
4970 return format_item_count_for_display (item_count
, TRUE
, TRUE
);
4973 if (file
->details
->size
== -1) {
4976 return g_format_size_for_display (file
->details
->size
);
4980 * nautilus_file_get_size_as_string_with_real_size:
4982 * Get a user-displayable string representing a file size. The caller
4983 * is responsible for g_free-ing this string. The string is an item
4984 * count for directories.
4985 * This function adds the real size in the string.
4986 * @file: NautilusFile representing the file in question.
4988 * Returns: Newly allocated string ready to display to the user.
4992 nautilus_file_get_size_as_string_with_real_size (NautilusFile
*file
)
4995 gboolean count_unreadable
;
4997 char * formated_plus_real
;
5004 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
5006 if (nautilus_file_is_directory (file
)) {
5007 if (!nautilus_file_get_directory_item_count (file
, &item_count
, &count_unreadable
)) {
5010 return format_item_count_for_display (item_count
, TRUE
, TRUE
);
5013 if (file
->details
->size
== -1) {
5017 formated
= g_format_size_for_display (file
->details
->size
);
5018 /* Do this in a separate stage so that we don't have to put G_GUINT64_FORMAT in the translated string */
5019 real_size
= g_strdup_printf (_("%"G_GUINT64_FORMAT
), (guint64
) file
->details
->size
);
5020 formated_plus_real
= g_strdup_printf (_("%s (%s bytes)"), formated
, real_size
);
5023 return formated_plus_real
;
5028 nautilus_file_get_deep_count_as_string_internal (NautilusFile
*file
,
5029 gboolean report_size
,
5030 gboolean report_directory_count
,
5031 gboolean report_file_count
)
5033 NautilusRequestStatus status
;
5034 guint directory_count
;
5036 guint unreadable_count
;
5040 /* Must ask for size or some kind of count, but not both. */
5041 g_return_val_if_fail (!report_size
|| (!report_directory_count
&& !report_file_count
), NULL
);
5042 g_return_val_if_fail (report_size
|| report_directory_count
|| report_file_count
, NULL
);
5048 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
5049 g_return_val_if_fail (nautilus_file_is_directory (file
), NULL
);
5051 status
= nautilus_file_get_deep_counts
5052 (file
, &directory_count
, &file_count
, &unreadable_count
, &total_size
, FALSE
);
5054 /* Check whether any info is available. */
5055 if (status
== NAUTILUS_REQUEST_NOT_STARTED
) {
5059 total_count
= file_count
+ directory_count
;
5061 if (total_count
== 0) {
5063 case NAUTILUS_REQUEST_IN_PROGRESS
:
5064 /* Don't return confident "zero" until we're finished looking,
5065 * because of next case.
5068 case NAUTILUS_REQUEST_DONE
:
5069 /* Don't return "zero" if we there were contents but we couldn't read them. */
5070 if (unreadable_count
!= 0) {
5077 /* Note that we don't distinguish the "everything was readable" case
5078 * from the "some things but not everything was readable" case here.
5079 * Callers can distinguish them using nautilus_file_get_deep_counts
5080 * directly if desired.
5083 return g_format_size_for_display (total_size
);
5086 return format_item_count_for_display (report_directory_count
5087 ? (report_file_count
? total_count
: directory_count
)
5089 report_directory_count
, report_file_count
);
5093 * nautilus_file_get_deep_size_as_string:
5095 * Get a user-displayable string representing the size of all contained
5096 * items (only makes sense for directories). The caller
5097 * is responsible for g_free-ing this string.
5098 * @file: NautilusFile representing the file in question.
5100 * Returns: Newly allocated string ready to display to the user.
5104 nautilus_file_get_deep_size_as_string (NautilusFile
*file
)
5106 return nautilus_file_get_deep_count_as_string_internal (file
, TRUE
, FALSE
, FALSE
);
5110 * nautilus_file_get_deep_total_count_as_string:
5112 * Get a user-displayable string representing the count of all contained
5113 * items (only makes sense for directories). The caller
5114 * is responsible for g_free-ing this string.
5115 * @file: NautilusFile representing the file in question.
5117 * Returns: Newly allocated string ready to display to the user.
5121 nautilus_file_get_deep_total_count_as_string (NautilusFile
*file
)
5123 return nautilus_file_get_deep_count_as_string_internal (file
, FALSE
, TRUE
, TRUE
);
5127 * nautilus_file_get_deep_file_count_as_string:
5129 * Get a user-displayable string representing the count of all contained
5130 * items, not including directories. It only makes sense to call this
5131 * function on a directory. The caller
5132 * is responsible for g_free-ing this string.
5133 * @file: NautilusFile representing the file in question.
5135 * Returns: Newly allocated string ready to display to the user.
5139 nautilus_file_get_deep_file_count_as_string (NautilusFile
*file
)
5141 return nautilus_file_get_deep_count_as_string_internal (file
, FALSE
, FALSE
, TRUE
);
5145 * nautilus_file_get_deep_directory_count_as_string:
5147 * Get a user-displayable string representing the count of all contained
5148 * directories. It only makes sense to call this
5149 * function on a directory. The caller
5150 * is responsible for g_free-ing this string.
5151 * @file: NautilusFile representing the file in question.
5153 * Returns: Newly allocated string ready to display to the user.
5157 nautilus_file_get_deep_directory_count_as_string (NautilusFile
*file
)
5159 return nautilus_file_get_deep_count_as_string_internal (file
, FALSE
, TRUE
, FALSE
);
5163 * nautilus_file_get_string_attribute:
5165 * Get a user-displayable string from a named attribute. Use g_free to
5166 * free this string. If the value is unknown, returns NULL. You can call
5167 * nautilus_file_get_string_attribute_with_default if you want a non-NULL
5170 * @file: NautilusFile representing the file in question.
5171 * @attribute_name: The name of the desired attribute. The currently supported
5172 * set includes "name", "type", "mime_type", "size", "deep_size", "deep_directory_count",
5173 * "deep_file_count", "deep_total_count", "date_modified", "date_changed", "date_accessed",
5174 * "date_permissions", "owner", "group", "permissions", "octal_permissions", "uri", "where",
5175 * "link_target", "volume", "free_space", "selinux_context"
5177 * Returns: Newly allocated string ready to display to the user, or NULL
5178 * if the value is unknown or @attribute_name is not supported.
5182 nautilus_file_get_string_attribute_q (NautilusFile
*file
, GQuark attribute_q
)
5184 char *extension_attribute
;
5186 if (attribute_q
== attribute_name_q
) {
5187 return nautilus_file_get_display_name (file
);
5189 if (attribute_q
== attribute_type_q
) {
5190 return nautilus_file_get_type_as_string (file
);
5192 if (attribute_q
== attribute_mime_type_q
) {
5193 return nautilus_file_get_mime_type (file
);
5195 if (attribute_q
== attribute_size_q
) {
5196 return nautilus_file_get_size_as_string (file
);
5198 if (attribute_q
== attribute_size_detail_q
) {
5199 return nautilus_file_get_size_as_string_with_real_size (file
);
5201 if (attribute_q
== attribute_deep_size_q
) {
5202 return nautilus_file_get_deep_size_as_string (file
);
5204 if (attribute_q
== attribute_deep_file_count_q
) {
5205 return nautilus_file_get_deep_file_count_as_string (file
);
5207 if (attribute_q
== attribute_deep_directory_count_q
) {
5208 return nautilus_file_get_deep_directory_count_as_string (file
);
5210 if (attribute_q
== attribute_deep_total_count_q
) {
5211 return nautilus_file_get_deep_total_count_as_string (file
);
5213 if (attribute_q
== attribute_date_modified_q
) {
5214 return nautilus_file_get_date_as_string (file
,
5215 NAUTILUS_DATE_TYPE_MODIFIED
);
5217 if (attribute_q
== attribute_date_changed_q
) {
5218 return nautilus_file_get_date_as_string (file
,
5219 NAUTILUS_DATE_TYPE_CHANGED
);
5221 if (attribute_q
== attribute_date_accessed_q
) {
5222 return nautilus_file_get_date_as_string (file
,
5223 NAUTILUS_DATE_TYPE_ACCESSED
);
5225 if (attribute_q
== attribute_date_permissions_q
) {
5226 return nautilus_file_get_date_as_string (file
,
5227 NAUTILUS_DATE_TYPE_PERMISSIONS_CHANGED
);
5229 if (attribute_q
== attribute_permissions_q
) {
5230 return nautilus_file_get_permissions_as_string (file
);
5232 if (attribute_q
== attribute_selinux_context_q
) {
5233 return nautilus_file_get_selinux_context (file
);
5235 if (attribute_q
== attribute_octal_permissions_q
) {
5236 return nautilus_file_get_octal_permissions_as_string (file
);
5238 if (attribute_q
== attribute_owner_q
) {
5239 return nautilus_file_get_owner_as_string (file
, TRUE
);
5241 if (attribute_q
== attribute_group_q
) {
5242 return nautilus_file_get_group_name (file
);
5244 if (attribute_q
== attribute_uri_q
) {
5245 return nautilus_file_get_uri (file
);
5247 if (attribute_q
== attribute_where_q
) {
5248 return nautilus_file_get_where_string (file
);
5250 if (attribute_q
== attribute_link_target_q
) {
5251 return nautilus_file_get_symbolic_link_target_path (file
);
5253 if (attribute_q
== attribute_volume_q
) {
5254 return nautilus_file_get_volume_name (file
);
5256 if (attribute_q
== attribute_free_space_q
) {
5257 return nautilus_file_get_volume_free_space (file
);
5260 extension_attribute
= NULL
;
5262 if (file
->details
->pending_extension_attributes
) {
5263 extension_attribute
= g_hash_table_lookup (file
->details
->pending_extension_attributes
,
5264 GINT_TO_POINTER (attribute_q
));
5267 if (extension_attribute
== NULL
&& file
->details
->extension_attributes
) {
5268 extension_attribute
= g_hash_table_lookup (file
->details
->extension_attributes
,
5269 GINT_TO_POINTER (attribute_q
));
5272 return g_strdup (extension_attribute
);
5276 nautilus_file_get_string_attribute (NautilusFile
*file
, const char *attribute_name
)
5278 return nautilus_file_get_string_attribute_q (file
, g_quark_from_string (attribute_name
));
5283 * nautilus_file_get_string_attribute_with_default:
5285 * Get a user-displayable string from a named attribute. Use g_free to
5286 * free this string. If the value is unknown, returns a string representing
5287 * the unknown value, which varies with attribute. You can call
5288 * nautilus_file_get_string_attribute if you want NULL instead of a default
5291 * @file: NautilusFile representing the file in question.
5292 * @attribute_name: The name of the desired attribute. See the description of
5293 * nautilus_file_get_string for the set of available attributes.
5295 * Returns: Newly allocated string ready to display to the user, or a string
5296 * such as "unknown" if the value is unknown or @attribute_name is not supported.
5300 nautilus_file_get_string_attribute_with_default_q (NautilusFile
*file
, GQuark attribute_q
)
5304 gboolean count_unreadable
;
5305 NautilusRequestStatus status
;
5307 result
= nautilus_file_get_string_attribute_q (file
, attribute_q
);
5308 if (result
!= NULL
) {
5312 /* Supply default values for the ones we know about. */
5313 /* FIXME bugzilla.gnome.org 40646:
5314 * Use hash table and switch statement or function pointers for speed?
5316 if (attribute_q
== attribute_size_q
) {
5317 if (!nautilus_file_should_show_directory_item_count (file
)) {
5318 return g_strdup ("--");
5320 count_unreadable
= FALSE
;
5321 if (nautilus_file_is_directory (file
)) {
5322 nautilus_file_get_directory_item_count (file
, &item_count
, &count_unreadable
);
5324 return g_strdup (count_unreadable
? _("? items") : "...");
5326 if (attribute_q
== attribute_deep_size_q
) {
5327 status
= nautilus_file_get_deep_counts (file
, NULL
, NULL
, NULL
, NULL
, FALSE
);
5328 if (status
== NAUTILUS_REQUEST_DONE
) {
5329 /* This means no contents at all were readable */
5330 return g_strdup (_("? bytes"));
5332 return g_strdup ("...");
5334 if (attribute_q
== attribute_deep_file_count_q
5335 || attribute_q
== attribute_deep_directory_count_q
5336 || attribute_q
== attribute_deep_total_count_q
) {
5337 status
= nautilus_file_get_deep_counts (file
, NULL
, NULL
, NULL
, NULL
, FALSE
);
5338 if (status
== NAUTILUS_REQUEST_DONE
) {
5339 /* This means no contents at all were readable */
5340 return g_strdup (_("? items"));
5342 return g_strdup ("...");
5344 if (attribute_q
== attribute_type_q
) {
5345 return g_strdup (_("unknown type"));
5347 if (attribute_q
== attribute_mime_type_q
) {
5348 return g_strdup (_("unknown MIME type"));
5351 /* Fallback, use for both unknown attributes and attributes
5352 * for which we have no more appropriate default.
5354 return g_strdup (_("unknown"));
5358 nautilus_file_get_string_attribute_with_default (NautilusFile
*file
, const char *attribute_name
)
5360 return nautilus_file_get_string_attribute_with_default_q (file
, g_quark_from_string (attribute_name
));
5366 * Get a user-displayable string representing a file type. The caller
5367 * is responsible for g_free-ing this string.
5368 * @file: NautilusFile representing the file in question.
5370 * Returns: Newly allocated string ready to display to the user.
5374 get_description (NautilusFile
*file
)
5376 const char *mime_type
;
5379 g_assert (NAUTILUS_IS_FILE (file
));
5381 mime_type
= eel_ref_str_peek (file
->details
->mime_type
);
5382 if (eel_str_is_empty (mime_type
)) {
5386 if (g_content_type_is_unknown (mime_type
) &&
5387 nautilus_file_is_executable (file
)) {
5388 return g_strdup (_("program"));
5391 description
= g_content_type_get_description (mime_type
);
5392 if (!eel_str_is_empty (description
)) {
5396 return g_strdup (mime_type
);
5399 /* Takes ownership of string */
5401 update_description_for_link (NautilusFile
*file
, char *string
)
5405 if (nautilus_file_is_symbolic_link (file
)) {
5406 g_assert (!nautilus_file_is_broken_symbolic_link (file
));
5407 if (string
== NULL
) {
5408 return g_strdup (_("link"));
5410 /* Note to localizers: convert file type string for file
5411 * (e.g. "folder", "plain text") to file type for symbolic link
5412 * to that kind of file (e.g. "link to folder").
5414 res
= g_strdup_printf (_("Link to %s"), string
);
5423 nautilus_file_get_type_as_string (NautilusFile
*file
)
5429 if (nautilus_file_is_broken_symbolic_link (file
)) {
5430 return g_strdup (_("link (broken)"));
5433 return update_description_for_link (file
, get_description (file
));
5437 * nautilus_file_get_file_type
5439 * Return this file's type.
5440 * @file: NautilusFile representing the file in question.
5442 * Returns: The type.
5446 nautilus_file_get_file_type (NautilusFile
*file
)
5449 return G_FILE_TYPE_UNKNOWN
;
5452 return file
->details
->type
;
5456 * nautilus_file_get_mime_type
5458 * Return this file's default mime type.
5459 * @file: NautilusFile representing the file in question.
5461 * Returns: The mime type.
5465 nautilus_file_get_mime_type (NautilusFile
*file
)
5468 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
5469 if (file
->details
->mime_type
!= NULL
) {
5470 return g_strdup (eel_ref_str_peek (file
->details
->mime_type
));
5473 return g_strdup ("application/octet-stream");
5477 * nautilus_file_is_mime_type
5479 * Check whether a file is of a particular MIME type, or inherited
5481 * @file: NautilusFile representing the file in question.
5482 * @mime_type: The MIME-type string to test (e.g. "text/plain")
5484 * Return value: TRUE if @mime_type exactly matches the
5489 nautilus_file_is_mime_type (NautilusFile
*file
, const char *mime_type
)
5491 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
5492 g_return_val_if_fail (mime_type
!= NULL
, FALSE
);
5494 if (file
->details
->mime_type
== NULL
) {
5497 return g_content_type_is_a (eel_ref_str_peek (file
->details
->mime_type
),
5502 nautilus_file_is_launchable (NautilusFile
*file
)
5504 gboolean type_can_be_executable
;
5506 type_can_be_executable
= FALSE
;
5507 if (file
->details
->mime_type
!= NULL
) {
5508 type_can_be_executable
=
5509 g_content_type_can_be_executable (eel_ref_str_peek (file
->details
->mime_type
));
5512 return type_can_be_executable
&&
5513 nautilus_file_can_get_permissions (file
) &&
5514 nautilus_file_can_execute (file
) &&
5515 nautilus_file_is_executable (file
) &&
5516 !nautilus_file_is_directory (file
);
5521 * nautilus_file_get_emblem_icons
5523 * Return the list of names of emblems that this file should display,
5524 * in canonical order.
5525 * @file: NautilusFile representing the file in question.
5527 * Returns: A list of emblem names.
5531 nautilus_file_get_emblem_icons (NautilusFile
*file
,
5534 GList
*keywords
, *l
;
5545 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
5547 keywords
= nautilus_file_get_keywords (file
);
5548 keywords
= prepend_automatic_keywords (file
, keywords
);
5551 for (l
= keywords
; l
!= NULL
; l
= l
->next
) {
5554 #ifdef TRASH_IS_FAST_ENOUGH
5555 if (strcmp (keyword
, NAUTILUS_FILE_EMBLEM_NAME_TRASH
) == 0) {
5557 gboolean file_is_trash
;
5558 /* Leave out the trash emblem for the trash itself, since
5559 * putting a trash emblem on a trash icon is gilding the
5562 uri
= nautilus_file_get_uri (file
);
5563 file_is_trash
= strcmp (uri
, EEL_TRASH_URI
) == 0;
5565 if (file_is_trash
) {
5571 for (i
= 0; exclude
[i
] != NULL
; i
++) {
5572 if (strcmp (exclude
[i
], keyword
) == 0) {
5578 icon_name
= nautilus_icon_get_emblem_icon_by_name (keyword
);
5579 icon
= g_themed_icon_new (icon_name
);
5581 icons
= g_list_prepend (icons
, icon
);
5584 eel_g_list_free_deep (keywords
);
5590 nautilus_file_get_emblem_pixbufs (NautilusFile
*file
,
5592 gboolean force_size
,
5599 NautilusIconInfo
*icon_info
;
5601 icons
= nautilus_file_get_emblem_icons (file
, exclude
);
5604 for (l
= icons
; l
!= NULL
; l
= l
->next
) {
5607 icon_info
= nautilus_icon_info_lookup (icon
, size
);
5609 pixbuf
= nautilus_icon_info_get_pixbuf_nodefault_at_size (icon_info
, size
);
5611 pixbuf
= nautilus_icon_info_get_pixbuf_nodefault (icon_info
);
5615 pixbufs
= g_list_prepend (pixbufs
, pixbuf
);
5619 g_object_unref (icon_info
);
5620 g_object_unref (icon
);
5622 g_list_free (icons
);
5624 return g_list_reverse (pixbufs
);
5630 sort_keyword_list_and_remove_duplicates (GList
*keywords
)
5633 GList
*duplicate_link
;
5635 if (keywords
!= NULL
) {
5636 keywords
= eel_g_str_list_alphabetize (keywords
);
5639 while (p
->next
!= NULL
) {
5640 if (strcmp ((const char *) p
->data
, (const char *) p
->next
->data
) == 0) {
5641 duplicate_link
= p
->next
;
5642 keywords
= g_list_remove_link (keywords
, duplicate_link
);
5643 eel_g_list_free_deep (duplicate_link
);
5654 * nautilus_file_get_keywords
5656 * Return this file's keywords.
5657 * @file: NautilusFile representing the file in question.
5659 * Returns: A list of keywords.
5663 nautilus_file_get_keywords (NautilusFile
*file
)
5671 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
5673 /* Put all the keywords into a list. */
5674 keywords
= nautilus_file_get_metadata_list
5675 (file
, "keyword", "name");
5677 keywords
= g_list_concat (keywords
, eel_g_str_list_copy (file
->details
->extension_emblems
));
5678 keywords
= g_list_concat (keywords
, eel_g_str_list_copy (file
->details
->pending_extension_emblems
));
5680 return sort_keyword_list_and_remove_duplicates (keywords
);
5684 * nautilus_file_set_keywords
5686 * Change this file's keywords.
5687 * @file: NautilusFile representing the file in question.
5688 * @keywords: New set of keywords (a GList of strings).
5692 nautilus_file_set_keywords (NautilusFile
*file
, GList
*keywords
)
5694 GList
*canonical_keywords
;
5696 /* Invalidate the emblem compare cache */
5697 g_free (file
->details
->compare_by_emblem_cache
);
5698 file
->details
->compare_by_emblem_cache
= NULL
;
5700 g_return_if_fail (NAUTILUS_IS_FILE (file
));
5702 canonical_keywords
= sort_keyword_list_and_remove_duplicates
5703 (g_list_copy (keywords
));
5704 nautilus_file_set_metadata_list
5705 (file
, "keyword", "name", canonical_keywords
);
5706 g_list_free (canonical_keywords
);
5710 * nautilus_file_is_symbolic_link
5712 * Check if this file is a symbolic link.
5713 * @file: NautilusFile representing the file in question.
5715 * Returns: True if the file is a symbolic link.
5719 nautilus_file_is_symbolic_link (NautilusFile
*file
)
5721 return file
->details
->is_symlink
;
5725 nautilus_file_is_mountpoint (NautilusFile
*file
)
5727 return file
->details
->is_mountpoint
;
5731 nautilus_file_get_mount (NautilusFile
*file
)
5733 if (file
->details
->mount
) {
5734 return g_object_ref (file
->details
->mount
);
5740 * nautilus_file_is_broken_symbolic_link
5742 * Check if this file is a symbolic link with a missing target.
5743 * @file: NautilusFile representing the file in question.
5745 * Returns: True if the file is a symbolic link with a missing target.
5749 nautilus_file_is_broken_symbolic_link (NautilusFile
*file
)
5755 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
5757 /* Non-broken symbolic links return the target's type for get_file_type. */
5758 return nautilus_file_get_file_type (file
) == G_FILE_TYPE_SYMBOLIC_LINK
;
5762 * nautilus_file_get_volume_free_space
5763 * Get a nicely formatted char with free space on the file's volume
5764 * @file: NautilusFile representing the file in question.
5766 * Returns: newly-allocated copy of file size in a formatted string
5769 nautilus_file_get_volume_free_space (NautilusFile
*file
)
5778 location
= nautilus_file_get_location (file
);
5779 info
= g_file_query_filesystem_info (location
, G_FILE_ATTRIBUTE_FILESYSTEM_FREE
, NULL
, NULL
);
5781 if (g_file_info_has_attribute (info
, G_FILE_ATTRIBUTE_FILESYSTEM_FREE
)) {
5782 free_space
= g_file_info_get_attribute_uint64 (info
, G_FILE_ATTRIBUTE_FILESYSTEM_FREE
);
5783 res
= g_format_size_for_display (free_space
);
5785 g_object_unref (info
);
5787 g_object_unref (location
);
5793 * nautilus_file_get_volume_name
5794 * Get the path of the volume the file resides on
5795 * @file: NautilusFile representing the file in question.
5797 * Returns: newly-allocated copy of the volume name of the target file,
5798 * if the volume name isn't set, it returns the mount path of the volume
5801 nautilus_file_get_volume_name (NautilusFile
*file
)
5809 location
= nautilus_file_get_location (file
);
5810 mount
= g_file_find_enclosing_mount (location
, NULL
, NULL
);
5812 res
= g_strdup (g_mount_get_name (mount
));
5813 g_object_unref (mount
);
5815 g_object_unref (location
);
5821 * nautilus_file_get_symbolic_link_target_path
5823 * Get the file path of the target of a symbolic link. It is an error
5824 * to call this function on a file that isn't a symbolic link.
5825 * @file: NautilusFile representing the symbolic link in question.
5827 * Returns: newly-allocated copy of the file path of the target of the symbolic link.
5830 nautilus_file_get_symbolic_link_target_path (NautilusFile
*file
)
5832 g_return_val_if_fail (nautilus_file_is_symbolic_link (file
), NULL
);
5834 return g_strdup (file
->details
->symlink_name
);
5838 * nautilus_file_get_symbolic_link_target_uri
5840 * Get the uri of the target of a symbolic link. It is an error
5841 * to call this function on a file that isn't a symbolic link.
5842 * @file: NautilusFile representing the symbolic link in question.
5844 * Returns: newly-allocated copy of the uri of the target of the symbolic link.
5847 nautilus_file_get_symbolic_link_target_uri (NautilusFile
*file
)
5849 GFile
*location
, *parent
, *target
;
5852 g_return_val_if_fail (nautilus_file_is_symbolic_link (file
), NULL
);
5854 if (file
->details
->symlink_name
== NULL
) {
5859 location
= nautilus_file_get_location (file
);
5860 parent
= g_file_get_parent (location
);
5861 g_object_unref (location
);
5863 target
= g_file_resolve_relative_path (parent
, file
->details
->symlink_name
);
5864 g_object_unref (parent
);
5869 target_uri
= g_file_get_uri (target
);
5870 g_object_unref (target
);
5877 * nautilus_file_is_nautilus_link
5879 * Check if this file is a "nautilus link", meaning a historical
5880 * nautilus xml link file or a desktop file.
5881 * @file: NautilusFile representing the file in question.
5883 * Returns: True if the file is a nautilus link.
5887 nautilus_file_is_nautilus_link (NautilusFile
*file
)
5889 /* NOTE: I removed the historical link here, because i don't think we
5890 even detect that mimetype anymore */
5891 return nautilus_file_is_mime_type (file
, "application/x-desktop");
5895 * nautilus_file_is_directory
5897 * Check if this file is a directory.
5898 * @file: NautilusFile representing the file in question.
5900 * Returns: TRUE if @file is a directory.
5904 nautilus_file_is_directory (NautilusFile
*file
)
5906 return nautilus_file_get_file_type (file
) == G_FILE_TYPE_DIRECTORY
;
5910 * nautilus_file_is_in_trash
5912 * Check if this file is a file in trash.
5913 * @file: NautilusFile representing the file in question.
5915 * Returns: TRUE if @file is in a trash.
5919 nautilus_file_is_in_trash (NautilusFile
*file
)
5921 g_assert (NAUTILUS_IS_FILE (file
));
5923 return nautilus_directory_is_in_trash (file
->details
->directory
);
5927 nautilus_file_get_file_info_error (NautilusFile
*file
)
5929 if (!file
->details
->get_info_failed
) {
5933 return file
->details
->get_info_error
;
5937 * nautilus_file_contains_text
5939 * Check if this file contains text.
5940 * This is private and is used to decide whether or not to read the top left text.
5941 * @file: NautilusFile representing the file in question.
5943 * Returns: TRUE if @file has a text MIME type.
5947 nautilus_file_contains_text (NautilusFile
*file
)
5953 /* All text files inherit from text/plain */
5954 return nautilus_file_is_mime_type (file
, "text/plain");
5958 * nautilus_file_is_executable
5960 * Check if this file is executable at all.
5961 * @file: NautilusFile representing the file in question.
5963 * Returns: TRUE if any of the execute bits are set. FALSE if
5964 * not, or if the permissions are unknown.
5968 nautilus_file_is_executable (NautilusFile
*file
)
5970 if (!file
->details
->has_permissions
) {
5971 /* File's permissions field is not valid.
5972 * Can't access specific permissions, so return FALSE.
5977 return file
->details
->can_execute
;
5981 * nautilus_file_peek_top_left_text
5983 * Peek at the text from the top left of the file.
5984 * @file: NautilusFile representing the file in question.
5986 * Returns: NULL if there is no text readable, otherwise, the text.
5987 * This string is owned by the file object and should not
5988 * be kept around or freed.
5992 nautilus_file_peek_top_left_text (NautilusFile
*file
,
5993 gboolean need_large_text
,
5994 gboolean
*needs_loading
)
5996 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
5998 if (!nautilus_file_should_get_top_left_text (file
)) {
5999 if (needs_loading
) {
6000 *needs_loading
= FALSE
;
6005 if (needs_loading
) {
6006 *needs_loading
= !file
->details
->top_left_text_is_up_to_date
;
6007 if (need_large_text
) {
6008 *needs_loading
|= file
->details
->got_top_left_text
!= file
->details
->got_large_top_left_text
;
6012 /* Show " ..." in the file until we read the contents in. */
6013 if (!file
->details
->got_top_left_text
) {
6015 if (nautilus_file_contains_text (file
)) {
6021 /* Show what we read in. */
6022 return file
->details
->top_left_text
;
6026 * nautilus_file_get_top_left_text
6028 * Get the text from the top left of the file.
6029 * @file: NautilusFile representing the file in question.
6031 * Returns: NULL if there is no text readable, otherwise, the text.
6035 nautilus_file_get_top_left_text (NautilusFile
*file
)
6037 return g_strdup (nautilus_file_peek_top_left_text (file
, FALSE
, NULL
));
6042 nautilus_file_mark_gone (NautilusFile
*file
)
6044 NautilusDirectory
*directory
;
6046 if (file
->details
->is_gone
)
6049 file
->details
->is_gone
= TRUE
;
6051 update_links_if_target (file
);
6053 /* Drop it from the symlink hash ! */
6054 remove_from_link_hash_table (file
);
6056 /* Let the directory know it's gone. */
6057 directory
= file
->details
->directory
;
6058 if (!nautilus_file_is_self_owned (file
)) {
6059 nautilus_directory_remove_file (directory
, file
);
6062 nautilus_file_clear_info (file
);
6064 /* FIXME bugzilla.gnome.org 42429:
6065 * Maybe we can get rid of the name too eventually, but
6066 * for now that would probably require too many if statements
6067 * everywhere anyone deals with the name. Maybe we can give it
6068 * a hard-coded "<deleted>" name or something.
6073 * nautilus_file_changed
6075 * Notify the user that this file has changed.
6076 * @file: NautilusFile representing the file in question.
6079 nautilus_file_changed (NautilusFile
*file
)
6083 g_return_if_fail (NAUTILUS_IS_FILE (file
));
6085 if (nautilus_file_is_self_owned (file
)) {
6086 nautilus_file_emit_changed (file
);
6088 fake_list
.data
= file
;
6089 fake_list
.next
= NULL
;
6090 fake_list
.prev
= NULL
;
6091 nautilus_directory_emit_change_signals
6092 (file
->details
->directory
, &fake_list
);
6097 * nautilus_file_updated_deep_count_in_progress
6099 * Notify clients that a newer deep count is available for
6100 * the directory in question.
6103 nautilus_file_updated_deep_count_in_progress (NautilusFile
*file
) {
6104 GList
*link_files
, *node
;
6106 g_assert (NAUTILUS_IS_FILE (file
));
6107 g_assert (nautilus_file_is_directory (file
));
6109 /* Send out a signal. */
6110 g_signal_emit (file
, signals
[UPDATED_DEEP_COUNT_IN_PROGRESS
], 0, file
);
6112 /* Tell link files pointing to this object about the change. */
6113 link_files
= get_link_files (file
);
6114 for (node
= link_files
; node
!= NULL
; node
= node
->next
) {
6115 nautilus_file_updated_deep_count_in_progress (NAUTILUS_FILE (node
->data
));
6117 nautilus_file_list_free (link_files
);
6121 * nautilus_file_emit_changed
6123 * Emit a file changed signal.
6124 * This can only be called by the directory, since the directory
6125 * also has to emit a files_changed signal.
6127 * @file: NautilusFile representing the file in question.
6130 nautilus_file_emit_changed (NautilusFile
*file
)
6132 GList
*link_files
, *p
;
6134 g_assert (NAUTILUS_IS_FILE (file
));
6137 /* Invalidate the emblem compare cache. -- This is not the cleanest
6138 * place to do it but it is the one guaranteed bottleneck through
6139 * which all change notifications pass.
6141 g_free (file
->details
->compare_by_emblem_cache
);
6142 file
->details
->compare_by_emblem_cache
= NULL
;
6144 /* Send out a signal. */
6145 g_signal_emit (file
, signals
[CHANGED
], 0, file
);
6147 /* Tell link files pointing to this object about the change. */
6148 link_files
= get_link_files (file
);
6149 for (p
= link_files
; p
!= NULL
; p
= p
->next
) {
6150 if (p
->data
!= file
) {
6151 nautilus_file_changed (NAUTILUS_FILE (p
->data
));
6154 nautilus_file_list_free (link_files
);
6158 * nautilus_file_is_gone
6160 * Check if a file has already been deleted.
6161 * @file: NautilusFile representing the file in question.
6163 * Returns: TRUE if the file is already gone.
6166 nautilus_file_is_gone (NautilusFile
*file
)
6168 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
6170 return file
->details
->is_gone
;
6174 * nautilus_file_is_not_yet_confirmed
6176 * Check if we're in a state where we don't know if a file really
6177 * exists or not, before the initial I/O is complete.
6178 * @file: NautilusFile representing the file in question.
6180 * Returns: TRUE if the file is already gone.
6183 nautilus_file_is_not_yet_confirmed (NautilusFile
*file
)
6185 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
6187 return !file
->details
->got_file_info
;
6191 * nautilus_file_check_if_ready
6193 * Check whether the values for a set of file attributes are
6194 * currently available, without doing any additional work. This
6195 * is useful for callers that want to reflect updated information
6196 * when it is ready but don't want to force the work required to
6197 * obtain the information, which might be slow network calls, e.g.
6199 * @file: The file being queried.
6200 * @file_attributes: A bit-mask with the desired information.
6202 * Return value: TRUE if all of the specified attributes are currently readable.
6205 nautilus_file_check_if_ready (NautilusFile
*file
,
6206 NautilusFileAttributes file_attributes
)
6208 /* To be parallel with call_when_ready, return
6209 * TRUE for NULL file.
6215 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
6217 return EEL_CALL_METHOD_WITH_RETURN_VALUE
6218 (NAUTILUS_FILE_CLASS
, file
,
6219 check_if_ready
, (file
, file_attributes
));
6223 nautilus_file_call_when_ready (NautilusFile
*file
,
6224 NautilusFileAttributes file_attributes
,
6225 NautilusFileCallback callback
,
6226 gpointer callback_data
)
6230 (* callback
) (file
, callback_data
);
6234 g_return_if_fail (NAUTILUS_IS_FILE (file
));
6237 (NAUTILUS_FILE_CLASS
, file
,
6238 call_when_ready
, (file
, file_attributes
,
6239 callback
, callback_data
));
6243 nautilus_file_cancel_call_when_ready (NautilusFile
*file
,
6244 NautilusFileCallback callback
,
6245 gpointer callback_data
)
6247 g_return_if_fail (callback
!= NULL
);
6253 g_return_if_fail (NAUTILUS_IS_FILE (file
));
6256 (NAUTILUS_FILE_CLASS
, file
,
6257 cancel_call_when_ready
, (file
, callback
, callback_data
));
6261 invalidate_directory_count (NautilusFile
*file
)
6263 file
->details
->directory_count_is_up_to_date
= FALSE
;
6267 invalidate_deep_counts (NautilusFile
*file
)
6269 file
->details
->deep_counts_status
= NAUTILUS_REQUEST_NOT_STARTED
;
6273 invalidate_mime_list (NautilusFile
*file
)
6275 file
->details
->mime_list_is_up_to_date
= FALSE
;
6279 invalidate_top_left_text (NautilusFile
*file
)
6281 file
->details
->top_left_text_is_up_to_date
= FALSE
;
6285 invalidate_file_info (NautilusFile
*file
)
6287 file
->details
->file_info_is_up_to_date
= FALSE
;
6291 invalidate_link_info (NautilusFile
*file
)
6293 file
->details
->link_info_is_up_to_date
= FALSE
;
6297 invalidate_thumbnail (NautilusFile
*file
)
6299 file
->details
->thumbnail_is_up_to_date
= FALSE
;
6303 nautilus_file_invalidate_extension_info_internal (NautilusFile
*file
)
6305 file
->details
->pending_info_providers
=
6306 nautilus_module_get_extensions_for_type (NAUTILUS_TYPE_INFO_PROVIDER
);
6310 nautilus_file_invalidate_attributes_internal (NautilusFile
*file
,
6311 NautilusFileAttributes file_attributes
)
6319 if (NAUTILUS_IS_DESKTOP_ICON_FILE (file
)) {
6320 /* Desktop icon files are always up to date.
6321 * If we invalidate their attributes they
6322 * will lose data, so we just ignore them.
6327 nautilus_directory_set_up_request (&request
, file_attributes
);
6329 if (request
.directory_count
) {
6330 invalidate_directory_count (file
);
6332 if (request
.deep_count
) {
6333 invalidate_deep_counts (file
);
6335 if (request
.mime_list
) {
6336 invalidate_mime_list (file
);
6338 if (request
.file_info
) {
6339 invalidate_file_info (file
);
6341 if (request
.top_left_text
) {
6342 invalidate_top_left_text (file
);
6344 if (request
.link_info
) {
6345 invalidate_link_info (file
);
6347 if (request
.extension_info
) {
6348 nautilus_file_invalidate_extension_info_internal (file
);
6350 if (request
.thumbnail
) {
6351 invalidate_thumbnail (file
);
6354 /* FIXME bugzilla.gnome.org 45075: implement invalidating metadata */
6358 nautilus_file_has_open_window (NautilusFile
*file
)
6360 return file
->details
->has_open_window
;
6364 nautilus_file_set_has_open_window (NautilusFile
*file
,
6365 gboolean has_open_window
)
6367 has_open_window
= (has_open_window
!= FALSE
);
6369 if (file
->details
->has_open_window
!= has_open_window
) {
6370 file
->details
->has_open_window
= has_open_window
;
6371 nautilus_file_changed (file
);
6377 nautilus_file_is_thumbnailing (NautilusFile
*file
)
6379 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
6381 return file
->details
->is_thumbnailing
;
6385 nautilus_file_set_is_thumbnailing (NautilusFile
*file
,
6386 gboolean is_thumbnailing
)
6388 g_return_if_fail (NAUTILUS_IS_FILE (file
));
6390 file
->details
->is_thumbnailing
= is_thumbnailing
;
6395 * nautilus_file_invalidate_attributes
6397 * Invalidate the specified attributes and force a reload.
6398 * @file: NautilusFile representing the file in question.
6399 * @file_attributes: attributes to froget.
6403 nautilus_file_invalidate_attributes (NautilusFile
*file
,
6404 NautilusFileAttributes file_attributes
)
6406 /* Cancel possible in-progress loads of any of these attributes */
6407 nautilus_directory_cancel_loading_file_attributes (file
->details
->directory
,
6411 /* Actually invalidate the values */
6412 nautilus_file_invalidate_attributes_internal (file
, file_attributes
);
6414 nautilus_directory_add_file_to_work_queue (file
->details
->directory
, file
);
6416 /* Kick off I/O if necessary */
6417 nautilus_directory_async_state_changed (file
->details
->directory
);
6420 NautilusFileAttributes
6421 nautilus_file_get_all_attributes (void)
6423 return NAUTILUS_FILE_ATTRIBUTE_INFO
|
6424 NAUTILUS_FILE_ATTRIBUTE_LINK_INFO
|
6425 NAUTILUS_FILE_ATTRIBUTE_DEEP_COUNTS
|
6426 NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_COUNT
|
6427 NAUTILUS_FILE_ATTRIBUTE_DIRECTORY_ITEM_MIME_TYPES
|
6428 NAUTILUS_FILE_ATTRIBUTE_METADATA
|
6429 NAUTILUS_FILE_ATTRIBUTE_TOP_LEFT_TEXT
|
6430 NAUTILUS_FILE_ATTRIBUTE_LARGE_TOP_LEFT_TEXT
|
6431 NAUTILUS_FILE_ATTRIBUTE_EXTENSION_INFO
|
6432 NAUTILUS_FILE_ATTRIBUTE_THUMBNAIL
|
6433 NAUTILUS_FILE_ATTRIBUTE_MOUNT
;
6437 nautilus_file_invalidate_all_attributes (NautilusFile
*file
)
6439 NautilusFileAttributes all_attributes
;
6441 all_attributes
= nautilus_file_get_all_attributes ();
6442 nautilus_file_invalidate_attributes (file
, all_attributes
);
6447 * nautilus_file_dump
6449 * Debugging call, prints out the contents of the file
6452 * @file: file to dump.
6455 nautilus_file_dump (NautilusFile
*file
)
6457 long size
= file
->details
->deep_size
;
6459 const char *file_kind
;
6461 uri
= nautilus_file_get_uri (file
);
6462 g_print ("uri: %s \n", uri
);
6463 if (!file
->details
->got_file_info
) {
6464 g_print ("no file info \n");
6465 } else if (file
->details
->get_info_failed
) {
6466 g_print ("failed to get file info \n");
6468 g_print ("size: %ld \n", size
);
6469 switch (file
->details
->type
) {
6470 case G_FILE_TYPE_REGULAR
:
6471 file_kind
= "regular file";
6473 case G_FILE_TYPE_DIRECTORY
:
6474 file_kind
= "folder";
6476 case G_FILE_TYPE_SPECIAL
:
6477 file_kind
= "special";
6479 case G_FILE_TYPE_SYMBOLIC_LINK
:
6480 file_kind
= "symbolic link";
6482 case G_FILE_TYPE_UNKNOWN
:
6484 file_kind
= "unknown";
6487 g_print ("kind: %s \n", file_kind
);
6488 if (file
->details
->type
== G_FILE_TYPE_SYMBOLIC_LINK
) {
6489 g_print ("link to %s \n", file
->details
->symlink_name
);
6490 /* FIXME bugzilla.gnome.org 42430: add following of symlinks here */
6492 /* FIXME bugzilla.gnome.org 42431: add permissions and other useful stuff here */
6498 * nautilus_file_list_ref
6500 * Ref all the files in a list.
6501 * @list: GList of files.
6504 nautilus_file_list_ref (GList
*list
)
6506 g_list_foreach (list
, (GFunc
) nautilus_file_ref
, NULL
);
6511 * nautilus_file_list_unref
6513 * Unref all the files in a list.
6514 * @list: GList of files.
6517 nautilus_file_list_unref (GList
*list
)
6519 g_list_foreach (list
, (GFunc
) nautilus_file_unref
, NULL
);
6523 * nautilus_file_list_free
6525 * Free a list of files after unrefing them.
6526 * @list: GList of files.
6529 nautilus_file_list_free (GList
*list
)
6531 nautilus_file_list_unref (list
);
6536 * nautilus_file_list_copy
6538 * Copy the list of files, making a new ref of each,
6539 * @list: GList of files.
6542 nautilus_file_list_copy (GList
*list
)
6544 return g_list_copy (nautilus_file_list_ref (list
));
6548 compare_by_display_name_cover (gconstpointer a
, gconstpointer b
)
6550 return compare_by_display_name (NAUTILUS_FILE (a
), NAUTILUS_FILE (b
));
6554 * nautilus_file_list_sort_by_display_name
6556 * Sort the list of files by file name.
6557 * @list: GList of files.
6560 nautilus_file_list_sort_by_display_name (GList
*list
)
6562 return g_list_sort (list
, compare_by_display_name_cover
);
6565 static GList
*ready_data_list
= NULL
;
6570 GList
*remaining_files
;
6571 NautilusFileListCallback callback
;
6572 gpointer callback_data
;
6573 } FileListReadyData
;
6576 file_list_ready_data_free (FileListReadyData
*data
)
6580 l
= g_list_find (ready_data_list
, data
);
6582 ready_data_list
= g_list_delete_link (ready_data_list
, l
);
6584 nautilus_file_list_free (data
->file_list
);
6585 g_list_free (data
->remaining_files
);
6590 static FileListReadyData
*
6591 file_list_ready_data_new (GList
*file_list
,
6592 NautilusFileListCallback callback
,
6593 gpointer callback_data
)
6595 FileListReadyData
*data
;
6597 data
= g_new0 (FileListReadyData
, 1);
6598 data
->file_list
= nautilus_file_list_copy (file_list
);
6599 data
->remaining_files
= g_list_copy (file_list
);
6600 data
->callback
= callback
;
6601 data
->callback_data
= callback_data
;
6603 ready_data_list
= g_list_prepend (ready_data_list
, data
);
6609 file_list_file_ready_callback (NautilusFile
*file
,
6612 FileListReadyData
*data
;
6615 data
->remaining_files
= g_list_remove (data
->remaining_files
, file
);
6617 if (data
->remaining_files
== NULL
) {
6618 if (data
->callback
) {
6619 (*data
->callback
) (data
->file_list
, data
->callback_data
);
6622 file_list_ready_data_free (data
);
6627 nautilus_file_list_call_when_ready (GList
*file_list
,
6628 NautilusFileAttributes attributes
,
6629 NautilusFileListHandle
**handle
,
6630 NautilusFileListCallback callback
,
6631 gpointer callback_data
)
6634 FileListReadyData
*data
;
6637 g_return_if_fail (file_list
!= NULL
);
6639 data
= file_list_ready_data_new
6640 (file_list
, callback
, callback_data
);
6643 *handle
= (NautilusFileListHandle
*) data
;
6649 file
= NAUTILUS_FILE (l
->data
);
6650 /* Need to do this here, as the list can be modified by this call */
6652 nautilus_file_call_when_ready (file
,
6654 file_list_file_ready_callback
,
6660 nautilus_file_list_cancel_call_when_ready (NautilusFileListHandle
*handle
)
6664 FileListReadyData
*data
;
6666 g_return_if_fail (handle
!= NULL
);
6668 data
= (FileListReadyData
*) handle
;
6670 l
= g_list_find (ready_data_list
, data
);
6672 for (l
= data
->remaining_files
; l
!= NULL
; l
= l
->next
) {
6673 file
= NAUTILUS_FILE (l
->data
);
6676 (NAUTILUS_FILE_CLASS
, file
,
6677 cancel_call_when_ready
, (file
, file_list_file_ready_callback
, data
));
6680 file_list_ready_data_free (data
);
6685 try_to_make_utf8 (const char *text
, int *length
)
6687 static const char *encodings_to_try
[2];
6688 static int n_encodings_to_try
= 0;
6689 gsize converted_length
;
6690 GError
*conversion_error
;
6694 if (n_encodings_to_try
== 0) {
6695 const char *charset
;
6696 gboolean charset_is_utf8
;
6698 charset_is_utf8
= g_get_charset (&charset
);
6699 if (!charset_is_utf8
) {
6700 encodings_to_try
[n_encodings_to_try
++] = charset
;
6703 if (g_ascii_strcasecmp (charset
, "ISO-8859-1") != 0) {
6704 encodings_to_try
[n_encodings_to_try
++] = "ISO-8859-1";
6709 for (i
= 0; i
< n_encodings_to_try
; i
++) {
6710 conversion_error
= NULL
;
6711 utf8_text
= g_convert (text
, *length
,
6712 "UTF-8", encodings_to_try
[i
],
6713 NULL
, &converted_length
, &conversion_error
);
6714 if (utf8_text
!= NULL
) {
6715 *length
= converted_length
;
6718 g_error_free (conversion_error
);
6726 /* Extract the top left part of the read-in text. */
6728 nautilus_extract_top_left_text (const char *text
,
6738 const char *utf8_end
;
6740 int max_bytes
, max_lines
, max_cols
;
6743 max_bytes
= NAUTILUS_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_BYTES
;
6744 max_lines
= NAUTILUS_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_LINES
;
6745 max_cols
= NAUTILUS_FILE_LARGE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE
;
6747 max_bytes
= NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_BYTES
;
6748 max_lines
= NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_LINES
;
6749 max_cols
= NAUTILUS_FILE_TOP_LEFT_TEXT_MAXIMUM_CHARACTERS_PER_LINE
;
6756 /* Might be a partial utf8 character at the end if we didn't read whole file */
6757 validated
= g_utf8_validate (text
, length
, &utf8_end
);
6759 !(length
>= max_bytes
&&
6760 text
+ length
- utf8_end
< 6)) {
6761 text_copy
= try_to_make_utf8 (text
, &length
);
6763 } else if (!validated
) {
6764 length
= utf8_end
- text
;
6768 if (text
== NULL
|| length
== 0) {
6772 buffer
= g_string_new ("");
6773 end
= text
+ length
; in
= text
;
6775 for (line
= 0; line
< max_lines
; line
++) {
6776 /* Extract one line. */
6777 for (i
= 0; i
< max_cols
; ) {
6782 c
= g_utf8_get_char (in
);
6784 if (g_unichar_isprint (c
)) {
6785 g_string_append_unichar (buffer
, c
);
6789 in
= g_utf8_next_char (in
);
6795 /* Skip the rest of the line. */
6796 while (*in
!= '\n') {
6805 /* Put a new-line separator in. */
6806 g_string_append_c(buffer
, '\n');
6811 return g_string_free(buffer
, FALSE
);
6815 thumbnail_limit_changed_callback (gpointer user_data
)
6817 cached_thumbnail_limit
= eel_preferences_get_integer (NAUTILUS_PREFERENCES_IMAGE_FILE_THUMBNAIL_LIMIT
);
6819 /* Tell the world that icons might have changed. We could invent a narrower-scope
6820 * signal to mean only "thumbnails might have changed" if this ends up being slow
6823 emit_change_signals_for_all_files_in_all_directories ();
6827 thumbnail_size_changed_callback (gpointer user_data
)
6829 cached_thumbnail_size
= eel_preferences_get_integer (NAUTILUS_PREFERENCES_ICON_VIEW_THUMBNAIL_SIZE
);
6831 /* Tell the world that icons might have changed. We could invent a narrower-scope
6832 * signal to mean only "thumbnails might have changed" if this ends up being slow
6835 emit_change_signals_for_all_files_in_all_directories ();
6839 show_thumbnails_changed_callback (gpointer user_data
)
6841 show_image_thumbs
= eel_preferences_get_enum (NAUTILUS_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS
);
6843 /* Tell the world that icons might have changed. We could invent a narrower-scope
6844 * signal to mean only "thumbnails might have changed" if this ends up being slow
6847 emit_change_signals_for_all_files_in_all_directories ();
6851 mime_type_data_changed_callback (GObject
*signaller
, gpointer user_data
)
6853 /* Tell the world that icons might have changed. We could invent a narrower-scope
6854 * signal to mean only "thumbnails might have changed" if this ends up being slow
6857 emit_change_signals_for_all_files_in_all_directories ();
6861 icon_theme_changed_callback (GtkIconTheme
*icon_theme
,
6864 /* Clear all pixmap caches as the icon => pixmap lookup changed */
6865 nautilus_icon_info_clear_caches ();
6867 /* Tell the world that icons might have changed. We could invent a narrower-scope
6868 * signal to mean only "thumbnails might have changed" if this ends up being slow
6871 emit_change_signals_for_all_files_in_all_directories ();
6875 nautilus_file_class_init (NautilusFileClass
*class)
6877 GtkIconTheme
*icon_theme
;
6879 parent_class
= g_type_class_peek_parent (class);
6881 attribute_name_q
= g_quark_from_static_string ("name");
6882 attribute_size_q
= g_quark_from_static_string ("size");
6883 attribute_type_q
= g_quark_from_static_string ("type");
6884 attribute_modification_date_q
= g_quark_from_static_string ("modification_date");
6885 attribute_date_modified_q
= g_quark_from_static_string ("date_modified");
6886 attribute_accessed_date_q
= g_quark_from_static_string ("accessed_date");
6887 attribute_date_accessed_q
= g_quark_from_static_string ("date_accessed");
6888 attribute_emblems_q
= g_quark_from_static_string ("emblems");
6889 attribute_mime_type_q
= g_quark_from_static_string ("mime_type");
6890 attribute_size_detail_q
= g_quark_from_static_string ("size_detail");
6891 attribute_deep_size_q
= g_quark_from_static_string ("deep_size");
6892 attribute_deep_file_count_q
= g_quark_from_static_string ("deep_file_count");
6893 attribute_deep_directory_count_q
= g_quark_from_static_string ("deep_directory_count");
6894 attribute_deep_total_count_q
= g_quark_from_static_string ("deep_total_count");
6895 attribute_date_changed_q
= g_quark_from_static_string ("date_changed");
6896 attribute_date_permissions_q
= g_quark_from_static_string ("date_permissions");
6897 attribute_permissions_q
= g_quark_from_static_string ("permissions");
6898 attribute_selinux_context_q
= g_quark_from_static_string ("selinux_context");
6899 attribute_octal_permissions_q
= g_quark_from_static_string ("octal_permissions");
6900 attribute_owner_q
= g_quark_from_static_string ("owner");
6901 attribute_group_q
= g_quark_from_static_string ("group");
6902 attribute_uri_q
= g_quark_from_static_string ("uri");
6903 attribute_where_q
= g_quark_from_static_string ("where");
6904 attribute_link_target_q
= g_quark_from_static_string ("link_target");
6905 attribute_volume_q
= g_quark_from_static_string ("volume");
6906 attribute_free_space_q
= g_quark_from_static_string ("free_space");
6908 G_OBJECT_CLASS (class)->finalize
= finalize
;
6909 G_OBJECT_CLASS (class)->constructor
= nautilus_file_constructor
;
6912 g_signal_new ("changed",
6913 G_TYPE_FROM_CLASS (class),
6915 G_STRUCT_OFFSET (NautilusFileClass
, changed
),
6917 g_cclosure_marshal_VOID__VOID
,
6920 signals
[UPDATED_DEEP_COUNT_IN_PROGRESS
] =
6921 g_signal_new ("updated_deep_count_in_progress",
6922 G_TYPE_FROM_CLASS (class),
6924 G_STRUCT_OFFSET (NautilusFileClass
, updated_deep_count_in_progress
),
6926 g_cclosure_marshal_VOID__VOID
,
6929 g_type_class_add_private (class, sizeof (NautilusFileDetails
));
6932 eel_preferences_add_auto_enum (NAUTILUS_PREFERENCES_DATE_FORMAT
,
6935 thumbnail_limit_changed_callback (NULL
);
6936 eel_preferences_add_callback (NAUTILUS_PREFERENCES_IMAGE_FILE_THUMBNAIL_LIMIT
,
6937 thumbnail_limit_changed_callback
,
6939 thumbnail_size_changed_callback (NULL
);
6940 eel_preferences_add_callback (NAUTILUS_PREFERENCES_ICON_VIEW_THUMBNAIL_SIZE
,
6941 thumbnail_size_changed_callback
,
6943 show_thumbnails_changed_callback (NULL
);
6944 eel_preferences_add_callback (NAUTILUS_PREFERENCES_SHOW_IMAGE_FILE_THUMBNAILS
,
6945 show_thumbnails_changed_callback
,
6948 icon_theme
= gtk_icon_theme_get_default ();
6949 g_signal_connect_object (icon_theme
,
6951 G_CALLBACK (icon_theme_changed_callback
),
6954 g_signal_connect (nautilus_signaller_get_current (),
6955 "mime_data_changed",
6956 G_CALLBACK (mime_type_data_changed_callback
),
6961 nautilus_file_add_emblem (NautilusFile
*file
,
6962 const char *emblem_name
)
6964 if (file
->details
->pending_info_providers
) {
6965 file
->details
->pending_extension_emblems
= g_list_prepend (file
->details
->pending_extension_emblems
,
6966 g_strdup (emblem_name
));
6968 file
->details
->extension_emblems
= g_list_prepend (file
->details
->extension_emblems
,
6969 g_strdup (emblem_name
));
6972 nautilus_file_changed (file
);
6976 nautilus_file_add_string_attribute (NautilusFile
*file
,
6977 const char *attribute_name
,
6980 if (file
->details
->pending_info_providers
) {
6981 /* Lazily create hashtable */
6982 if (!file
->details
->pending_extension_attributes
) {
6983 file
->details
->pending_extension_attributes
=
6984 g_hash_table_new_full (g_direct_hash
, g_direct_equal
,
6986 (GDestroyNotify
)g_free
);
6988 g_hash_table_insert (file
->details
->pending_extension_attributes
,
6989 GINT_TO_POINTER (g_quark_from_string (attribute_name
)),
6992 if (!file
->details
->extension_attributes
) {
6993 file
->details
->extension_attributes
=
6994 g_hash_table_new_full (g_direct_hash
, g_direct_equal
,
6996 (GDestroyNotify
)g_free
);
6998 g_hash_table_insert (file
->details
->extension_attributes
,
6999 GINT_TO_POINTER (g_quark_from_string (attribute_name
)),
7003 nautilus_file_changed (file
);
7007 nautilus_file_invalidate_extension_info (NautilusFile
*file
)
7009 nautilus_file_invalidate_attributes (file
, NAUTILUS_FILE_ATTRIBUTE_EXTENSION_INFO
);
7013 nautilus_file_info_providers_done (NautilusFile
*file
)
7015 eel_g_list_free_deep (file
->details
->extension_emblems
);
7016 file
->details
->extension_emblems
= file
->details
->pending_extension_emblems
;
7017 file
->details
->pending_extension_emblems
= NULL
;
7019 if (file
->details
->extension_attributes
) {
7020 g_hash_table_destroy (file
->details
->extension_attributes
);
7023 file
->details
->extension_attributes
= file
->details
->pending_extension_attributes
;
7024 file
->details
->pending_extension_attributes
= NULL
;
7026 nautilus_file_changed (file
);
7030 nautilus_file_info_iface_init (NautilusFileInfoIface
*iface
)
7032 iface
->is_gone
= nautilus_file_is_gone
;
7033 iface
->get_name
= nautilus_file_get_name
;
7034 iface
->get_file_type
= nautilus_file_get_file_type
;
7035 iface
->get_location
= nautilus_file_get_location
;
7036 iface
->get_uri
= nautilus_file_get_uri
;
7037 iface
->get_parent_location
= nautilus_file_get_parent_location
;
7038 iface
->get_parent_uri
= nautilus_file_get_parent_uri
;
7039 iface
->get_parent_info
= nautilus_file_get_parent
;
7040 iface
->get_mount
= nautilus_file_get_mount
;
7041 iface
->get_uri_scheme
= nautilus_file_get_uri_scheme
;
7042 iface
->get_activation_uri
= nautilus_file_get_activation_uri
;
7043 iface
->get_mime_type
= nautilus_file_get_mime_type
;
7044 iface
->is_mime_type
= nautilus_file_is_mime_type
;
7045 iface
->is_directory
= nautilus_file_is_directory
;
7046 iface
->can_write
= nautilus_file_can_write
;
7047 iface
->add_emblem
= nautilus_file_add_emblem
;
7048 iface
->get_string_attribute
= nautilus_file_get_string_attribute
;
7049 iface
->add_string_attribute
= nautilus_file_add_string_attribute
;
7050 iface
->invalidate_extension_info
= nautilus_file_invalidate_extension_info
;
7053 #if !defined (NAUTILUS_OMIT_SELF_CHECK)
7056 nautilus_self_check_file (void)
7058 NautilusFile
*file_1
;
7059 NautilusFile
*file_2
;
7062 /* refcount checks */
7064 EEL_CHECK_INTEGER_RESULT (nautilus_directory_number_outstanding (), 0);
7066 file_1
= nautilus_file_get_by_uri ("file:///home/");
7068 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1
)->ref_count
, 1);
7069 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1
->details
->directory
)->ref_count
, 1);
7070 EEL_CHECK_INTEGER_RESULT (nautilus_directory_number_outstanding (), 1);
7072 nautilus_file_unref (file_1
);
7074 EEL_CHECK_INTEGER_RESULT (nautilus_directory_number_outstanding (), 0);
7076 file_1
= nautilus_file_get_by_uri ("file:///etc");
7077 file_2
= nautilus_file_get_by_uri ("file:///usr");
7080 list
= g_list_prepend (list
, file_1
);
7081 list
= g_list_prepend (list
, file_2
);
7083 nautilus_file_list_ref (list
);
7085 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1
)->ref_count
, 2);
7086 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2
)->ref_count
, 2);
7088 nautilus_file_list_unref (list
);
7090 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1
)->ref_count
, 1);
7091 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2
)->ref_count
, 1);
7093 nautilus_file_list_free (list
);
7095 EEL_CHECK_INTEGER_RESULT (nautilus_directory_number_outstanding (), 0);
7099 file_1
= nautilus_file_get_by_uri ("file:///home/");
7101 EEL_CHECK_STRING_RESULT (nautilus_file_get_name (file_1
), "home");
7103 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_get_by_uri ("file:///home/") == file_1
, TRUE
);
7104 nautilus_file_unref (file_1
);
7106 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_get_by_uri ("file:///home") == file_1
, TRUE
);
7107 nautilus_file_unref (file_1
);
7109 nautilus_file_unref (file_1
);
7111 file_1
= nautilus_file_get_by_uri ("file:///home");
7112 EEL_CHECK_STRING_RESULT (nautilus_file_get_name (file_1
), "home");
7113 nautilus_file_unref (file_1
);
7116 /* ALEX: I removed this, because it was breaking distchecks.
7117 * It used to work, but when canonical uris changed from
7118 * foo: to foo:/// it broke. I don't expect it to matter
7120 file_1
= nautilus_file_get_by_uri (":");
7121 EEL_CHECK_STRING_RESULT (nautilus_file_get_name (file_1
), ":");
7122 nautilus_file_unref (file_1
);
7125 file_1
= nautilus_file_get_by_uri ("eazel:");
7126 EEL_CHECK_STRING_RESULT (nautilus_file_get_name (file_1
), "eazel");
7127 nautilus_file_unref (file_1
);
7130 file_1
= nautilus_file_get_by_uri ("file:///etc");
7131 file_2
= nautilus_file_get_by_uri ("file:///usr");
7133 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_1
)->ref_count
, 1);
7134 EEL_CHECK_INTEGER_RESULT (G_OBJECT (file_2
)->ref_count
, 1);
7136 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_compare_for_sort (file_1
, file_2
, NAUTILUS_FILE_SORT_BY_DISPLAY_NAME
, FALSE
, FALSE
) < 0, TRUE
);
7137 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_compare_for_sort (file_1
, file_2
, NAUTILUS_FILE_SORT_BY_DISPLAY_NAME
, FALSE
, TRUE
) > 0, TRUE
);
7138 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_compare_for_sort (file_1
, file_1
, NAUTILUS_FILE_SORT_BY_DISPLAY_NAME
, FALSE
, FALSE
) == 0, TRUE
);
7139 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_compare_for_sort (file_1
, file_1
, NAUTILUS_FILE_SORT_BY_DISPLAY_NAME
, TRUE
, FALSE
) == 0, TRUE
);
7140 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_compare_for_sort (file_1
, file_1
, NAUTILUS_FILE_SORT_BY_DISPLAY_NAME
, FALSE
, TRUE
) == 0, TRUE
);
7141 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_compare_for_sort (file_1
, file_1
, NAUTILUS_FILE_SORT_BY_DISPLAY_NAME
, TRUE
, TRUE
) == 0, TRUE
);
7143 nautilus_file_unref (file_1
);
7144 nautilus_file_unref (file_2
);
7147 #endif /* !NAUTILUS_OMIT_SELF_CHECK */