1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
3 nautilus-directory.c: Nautilus directory 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-directory-private.h"
28 #include "nautilus-directory-metafile.h"
29 #include "nautilus-directory-notify.h"
30 #include "nautilus-file-attributes.h"
31 #include "nautilus-file-private.h"
32 #include "nautilus-file-utilities.h"
33 #include "nautilus-search-directory.h"
34 #include "nautilus-global-preferences.h"
35 #include "nautilus-lib-self-check-functions.h"
36 #include "nautilus-marshal.h"
37 #include "nautilus-metadata.h"
38 #include "nautilus-metafile.h"
39 #include "nautilus-desktop-directory.h"
40 #include "nautilus-vfs-directory.h"
41 #include <eel/eel-glib-extensions.h>
42 #include <eel/eel-gtk-macros.h>
43 #include <eel/eel-string.h>
44 #include <gtk/gtkmain.h>
45 #include <gtk/gtksignal.h>
55 static guint signals
[LAST_SIGNAL
];
57 /* Specifications for parallel-directory metafile. */
58 #define METAFILES_DIRECTORY_NAME "metafiles"
59 #define METAFILE_SUFFIX ".xml"
60 #define METAFILES_DIRECTORY_PERMISSIONS \
61 (S_IRUSR | S_IWUSR | S_IXUSR | \
62 S_IRGRP | S_IWGRP | S_IXGRP | \
63 S_IROTH | S_IWOTH | S_IXOTH)
65 static GHashTable
*directories
;
67 static void nautilus_directory_finalize (GObject
*object
);
68 static void nautilus_directory_init (gpointer object
,
70 static void nautilus_directory_class_init (NautilusDirectoryClass
*klass
);
71 static NautilusDirectory
*nautilus_directory_new (GFile
*location
);
72 static char * real_get_name_for_self_as_new_file (NautilusDirectory
*directory
);
73 static GList
* real_get_file_list (NautilusDirectory
*directory
);
74 static gboolean
real_is_editable (NautilusDirectory
*directory
);
75 static void set_directory_location (NautilusDirectory
*directory
,
78 EEL_CLASS_BOILERPLATE (NautilusDirectory
,
83 nautilus_directory_class_init (NautilusDirectoryClass
*klass
)
85 GObjectClass
*object_class
;
87 object_class
= G_OBJECT_CLASS (klass
);
89 object_class
->finalize
= nautilus_directory_finalize
;
91 signals
[FILES_ADDED
] =
92 g_signal_new ("files_added",
93 G_TYPE_FROM_CLASS (object_class
),
95 G_STRUCT_OFFSET (NautilusDirectoryClass
, files_added
),
97 g_cclosure_marshal_VOID__POINTER
,
98 G_TYPE_NONE
, 1, G_TYPE_POINTER
);
99 signals
[FILES_CHANGED
] =
100 g_signal_new ("files_changed",
101 G_TYPE_FROM_CLASS (object_class
),
103 G_STRUCT_OFFSET (NautilusDirectoryClass
, files_changed
),
105 g_cclosure_marshal_VOID__POINTER
,
106 G_TYPE_NONE
, 1, G_TYPE_POINTER
);
107 signals
[DONE_LOADING
] =
108 g_signal_new ("done_loading",
109 G_TYPE_FROM_CLASS (object_class
),
111 G_STRUCT_OFFSET (NautilusDirectoryClass
, done_loading
),
113 g_cclosure_marshal_VOID__VOID
,
115 signals
[LOAD_ERROR
] =
116 g_signal_new ("load_error",
117 G_TYPE_FROM_CLASS (object_class
),
119 G_STRUCT_OFFSET (NautilusDirectoryClass
, load_error
),
121 g_cclosure_marshal_VOID__POINTER
,
122 G_TYPE_NONE
, 1, G_TYPE_POINTER
);
124 klass
->get_name_for_self_as_new_file
= real_get_name_for_self_as_new_file
;
125 klass
->get_file_list
= real_get_file_list
;
126 klass
->is_editable
= real_is_editable
;
128 g_type_class_add_private (klass
, sizeof (NautilusDirectoryDetails
));
132 nautilus_directory_init (gpointer object
, gpointer klass
)
134 NautilusDirectory
*directory
;
136 directory
= NAUTILUS_DIRECTORY(object
);
138 directory
->details
= G_TYPE_INSTANCE_GET_PRIVATE ((directory
), NAUTILUS_TYPE_DIRECTORY
, NautilusDirectoryDetails
);
139 directory
->details
->file_hash
= g_hash_table_new (g_str_hash
, g_str_equal
);
140 directory
->details
->high_priority_queue
= nautilus_file_queue_new ();
141 directory
->details
->low_priority_queue
= nautilus_file_queue_new ();
142 directory
->details
->extension_queue
= nautilus_file_queue_new ();
143 directory
->details
->idle_queue
= nautilus_idle_queue_new ();
147 nautilus_directory_ref (NautilusDirectory
*directory
)
149 if (directory
== NULL
) {
153 g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory
), NULL
);
155 g_object_ref (directory
);
160 nautilus_directory_unref (NautilusDirectory
*directory
)
162 if (directory
== NULL
) {
166 g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory
));
168 g_object_unref (directory
);
172 nautilus_directory_finalize (GObject
*object
)
174 NautilusDirectory
*directory
;
176 directory
= NAUTILUS_DIRECTORY (object
);
178 g_hash_table_remove (directories
, directory
->details
->location
);
180 nautilus_directory_cancel (directory
);
181 g_assert (directory
->details
->count_in_progress
== NULL
);
182 g_assert (directory
->details
->top_left_read_state
== NULL
);
184 if (directory
->details
->monitor_list
!= NULL
) {
185 g_warning ("destroying a NautilusDirectory while it's being monitored");
186 eel_g_list_free_deep (directory
->details
->monitor_list
);
189 if (directory
->details
->monitor
!= NULL
) {
190 nautilus_monitor_cancel (directory
->details
->monitor
);
193 if (directory
->details
->metafile_monitored
) {
194 nautilus_directory_unregister_metadata_monitor (directory
);
197 if (directory
->details
->metafile
!= NULL
) {
198 g_object_unref (directory
->details
->metafile
);
201 if (directory
->details
->dequeue_pending_idle_id
!= 0) {
202 g_source_remove (directory
->details
->dequeue_pending_idle_id
);
205 if (directory
->details
->call_ready_idle_id
!= 0) {
206 g_source_remove (directory
->details
->call_ready_idle_id
);
209 if (directory
->details
->location
) {
210 g_object_unref (directory
->details
->location
);
213 g_assert (directory
->details
->file_list
== NULL
);
214 g_hash_table_destroy (directory
->details
->file_hash
);
216 if (directory
->details
->hidden_file_hash
) {
217 g_hash_table_destroy (directory
->details
->hidden_file_hash
);
220 nautilus_file_queue_destroy (directory
->details
->high_priority_queue
);
221 nautilus_file_queue_destroy (directory
->details
->low_priority_queue
);
222 nautilus_file_queue_destroy (directory
->details
->extension_queue
);
223 nautilus_idle_queue_destroy (directory
->details
->idle_queue
);
224 g_assert (directory
->details
->directory_load_in_progress
== NULL
);
225 g_assert (directory
->details
->count_in_progress
== NULL
);
226 g_assert (directory
->details
->dequeue_pending_idle_id
== 0);
227 eel_g_object_list_free (directory
->details
->pending_file_info
);
229 EEL_CALL_PARENT (G_OBJECT_CLASS
, finalize
, (object
));
233 invalidate_one_count (gpointer key
, gpointer value
, gpointer user_data
)
235 NautilusDirectory
*directory
;
237 g_assert (key
!= NULL
);
238 g_assert (NAUTILUS_IS_DIRECTORY (value
));
239 g_assert (user_data
== NULL
);
241 directory
= NAUTILUS_DIRECTORY (value
);
243 nautilus_directory_invalidate_count_and_mime_list (directory
);
247 filtering_changed_callback (gpointer callback_data
)
249 g_assert (callback_data
== NULL
);
251 /* Preference about which items to show has changed, so we
252 * can't trust any of our precomputed directory counts.
254 g_hash_table_foreach (directories
, invalidate_one_count
, NULL
);
258 emit_change_signals_for_all_files (NautilusDirectory
*directory
)
262 files
= g_list_copy (directory
->details
->file_list
);
263 if (directory
->details
->as_file
!= NULL
) {
264 files
= g_list_prepend (files
, directory
->details
->as_file
);
267 nautilus_file_list_ref (files
);
268 nautilus_directory_emit_change_signals (directory
, files
);
270 nautilus_file_list_free (files
);
274 collect_all_directories (gpointer key
, gpointer value
, gpointer callback_data
)
276 NautilusDirectory
*directory
;
280 location
= (GFile
*) key
;
281 directory
= NAUTILUS_DIRECTORY (value
);
282 dirs
= callback_data
;
284 *dirs
= g_list_prepend (*dirs
, nautilus_directory_ref (directory
));
288 emit_change_signals_for_all_files_in_all_directories (void)
291 NautilusDirectory
*directory
;
294 g_hash_table_foreach (directories
,
295 collect_all_directories
,
298 for (l
= dirs
; l
!= NULL
; l
= l
->next
) {
299 directory
= NAUTILUS_DIRECTORY (l
->data
);
300 emit_change_signals_for_all_files (directory
);
301 nautilus_directory_unref (directory
);
308 async_state_changed_one (gpointer key
, gpointer value
, gpointer user_data
)
310 NautilusDirectory
*directory
;
312 g_assert (key
!= NULL
);
313 g_assert (NAUTILUS_IS_DIRECTORY (value
));
314 g_assert (user_data
== NULL
);
316 directory
= NAUTILUS_DIRECTORY (value
);
318 nautilus_directory_async_state_changed (directory
);
319 emit_change_signals_for_all_files (directory
);
323 async_data_preference_changed_callback (gpointer callback_data
)
325 g_assert (callback_data
== NULL
);
327 /* Preference involving fetched async data has changed, so
328 * we have to kick off refetching all async data, and tell
329 * each file that it (might have) changed.
331 g_hash_table_foreach (directories
, async_state_changed_one
, NULL
);
335 add_preferences_callbacks (void)
337 nautilus_global_preferences_init ();
339 eel_preferences_add_callback (NAUTILUS_PREFERENCES_SHOW_HIDDEN_FILES
,
340 filtering_changed_callback
,
342 eel_preferences_add_callback (NAUTILUS_PREFERENCES_SHOW_BACKUP_FILES
,
343 filtering_changed_callback
,
345 eel_preferences_add_callback (NAUTILUS_PREFERENCES_SHOW_TEXT_IN_ICONS
,
346 async_data_preference_changed_callback
,
348 eel_preferences_add_callback (NAUTILUS_PREFERENCES_SHOW_DIRECTORY_ITEM_COUNTS
,
349 async_data_preference_changed_callback
,
351 eel_preferences_add_callback (NAUTILUS_PREFERENCES_DATE_FORMAT
,
352 async_data_preference_changed_callback
,
357 * nautilus_directory_get_by_uri:
358 * @uri: URI of directory to get.
360 * Get a directory given a uri.
361 * Creates the appropriate subclass given the uri mappings.
362 * Returns a referenced object, not a floating one. Unref when finished.
363 * If two windows are viewing the same uri, the directory object is shared.
366 nautilus_directory_get_internal (GFile
*location
, gboolean create
)
368 NautilusDirectory
*directory
;
370 /* Create the hash table first time through. */
371 if (directories
== NULL
) {
372 directories
= eel_g_hash_table_new_free_at_exit
373 (g_file_hash
, (GCompareFunc
)g_file_equal
, "nautilus-directory.c: directories");
375 add_preferences_callbacks ();
378 /* If the object is already in the hash table, look it up. */
380 directory
= g_hash_table_lookup (directories
,
382 if (directory
!= NULL
) {
383 nautilus_directory_ref (directory
);
385 /* Create a new directory object instead. */
386 directory
= nautilus_directory_new (location
);
387 if (directory
== NULL
) {
391 /* Put it in the hash table. */
392 g_hash_table_insert (directories
,
393 directory
->details
->location
,
401 nautilus_directory_get (GFile
*location
)
403 if (location
== NULL
) {
407 return nautilus_directory_get_internal (location
, TRUE
);
411 nautilus_directory_get_existing (GFile
*location
)
413 if (location
== NULL
) {
417 return nautilus_directory_get_internal (location
, FALSE
);
422 nautilus_directory_get_by_uri (const char *uri
)
424 NautilusDirectory
*directory
;
431 location
= g_file_new_for_uri (uri
);
433 directory
= nautilus_directory_get_internal (location
, TRUE
);
434 g_object_unref (location
);
439 nautilus_directory_get_for_file (NautilusFile
*file
)
442 NautilusDirectory
*directory
;
444 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), NULL
);
446 uri
= nautilus_file_get_uri (file
);
447 directory
= nautilus_directory_get_by_uri (uri
);
452 /* Returns a reffed NautilusFile object for this directory.
455 nautilus_directory_get_corresponding_file (NautilusDirectory
*directory
)
460 file
= nautilus_directory_get_existing_corresponding_file (directory
);
462 uri
= nautilus_directory_get_uri (directory
);
463 file
= nautilus_file_get_by_uri (uri
);
470 /* Returns a reffed NautilusFile object for this directory, but only if the
471 * NautilusFile object has already been created.
474 nautilus_directory_get_existing_corresponding_file (NautilusDirectory
*directory
)
479 file
= directory
->details
->as_file
;
481 nautilus_file_ref (file
);
485 uri
= nautilus_directory_get_uri (directory
);
486 file
= nautilus_file_get_existing_by_uri (uri
);
491 /* nautilus_directory_get_name_for_self_as_new_file:
493 * Get a name to display for the file representing this
494 * directory. This is called only when there's no VFS
495 * directory for this NautilusDirectory.
498 nautilus_directory_get_name_for_self_as_new_file (NautilusDirectory
*directory
)
500 g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory
), NULL
);
502 return EEL_CALL_METHOD_WITH_RETURN_VALUE
503 (NAUTILUS_DIRECTORY_CLASS
, directory
,
504 get_name_for_self_as_new_file
, (directory
));
508 real_get_name_for_self_as_new_file (NautilusDirectory
*directory
)
513 directory_uri
= nautilus_directory_get_uri (directory
);
515 colon
= strchr (directory_uri
, ':');
516 if (colon
== NULL
|| colon
== directory_uri
) {
517 name
= g_strdup (directory_uri
);
519 name
= g_strndup (directory_uri
, colon
- directory_uri
);
521 g_free (directory_uri
);
527 nautilus_directory_get_uri (NautilusDirectory
*directory
)
529 g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory
), NULL
);
531 return g_file_get_uri (directory
->details
->location
);
535 nautilus_directory_get_location (NautilusDirectory
*directory
)
537 g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory
), NULL
);
539 return g_object_ref (directory
->details
->location
);
542 static NautilusDirectory
*
543 nautilus_directory_new (GFile
*location
)
545 NautilusDirectory
*directory
;
548 uri
= g_file_get_uri (location
);
550 if (eel_uri_is_desktop (uri
)) {
551 directory
= NAUTILUS_DIRECTORY (g_object_new (NAUTILUS_TYPE_DESKTOP_DIRECTORY
, NULL
));
552 } else if (eel_uri_is_search (uri
)) {
553 directory
= NAUTILUS_DIRECTORY (g_object_new (NAUTILUS_TYPE_SEARCH_DIRECTORY
, NULL
));
554 } else if (g_str_has_suffix (uri
, NAUTILUS_SAVED_SEARCH_EXTENSION
)) {
555 directory
= NAUTILUS_DIRECTORY (nautilus_search_directory_new_from_saved_search (uri
));
557 directory
= NAUTILUS_DIRECTORY (g_object_new (NAUTILUS_TYPE_VFS_DIRECTORY
, NULL
));
560 set_directory_location (directory
, location
);
568 nautilus_directory_is_local (NautilusDirectory
*directory
)
570 g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory
), FALSE
);
572 if (directory
->details
->location
== NULL
) {
575 return g_file_is_native (directory
->details
->location
);
579 nautilus_directory_is_in_trash (NautilusDirectory
*directory
)
581 g_assert (NAUTILUS_IS_DIRECTORY (directory
));
583 if (directory
->details
->location
== NULL
) {
587 return g_file_has_uri_scheme (directory
->details
->location
, "trash");
591 nautilus_directory_are_all_files_seen (NautilusDirectory
*directory
)
593 g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory
), FALSE
);
595 return EEL_CALL_METHOD_WITH_RETURN_VALUE
596 (NAUTILUS_DIRECTORY_CLASS
, directory
,
597 are_all_files_seen
, (directory
));
601 add_to_hash_table (NautilusDirectory
*directory
, NautilusFile
*file
, GList
*node
)
605 name
= eel_ref_str_peek (file
->details
->name
);
607 g_assert (node
!= NULL
);
608 g_assert (g_hash_table_lookup (directory
->details
->file_hash
,
610 g_hash_table_insert (directory
->details
->file_hash
, (char *) name
, node
);
614 extract_from_hash_table (NautilusDirectory
*directory
, NautilusFile
*file
)
619 name
= eel_ref_str_peek (file
->details
->name
);
624 /* Find the list node in the hash table. */
625 node
= g_hash_table_lookup (directory
->details
->file_hash
, name
);
626 g_hash_table_remove (directory
->details
->file_hash
, name
);
632 nautilus_directory_add_file (NautilusDirectory
*directory
, NautilusFile
*file
)
636 g_assert (NAUTILUS_IS_DIRECTORY (directory
));
637 g_assert (NAUTILUS_IS_FILE (file
));
638 g_assert (file
->details
->name
!= NULL
);
641 node
= g_list_prepend (directory
->details
->file_list
, file
);
642 directory
->details
->file_list
= node
;
644 /* Add to hash table. */
645 add_to_hash_table (directory
, file
, node
);
647 directory
->details
->confirmed_file_count
++;
649 /* Ref if we are monitoring. */
650 if (nautilus_directory_is_file_list_monitored (directory
)) {
651 nautilus_file_ref (file
);
652 nautilus_directory_add_file_to_work_queue (directory
, file
);
657 nautilus_directory_remove_file (NautilusDirectory
*directory
, NautilusFile
*file
)
661 g_assert (NAUTILUS_IS_DIRECTORY (directory
));
662 g_assert (NAUTILUS_IS_FILE (file
));
663 g_assert (file
->details
->name
!= NULL
);
665 /* Find the list node in the hash table. */
666 node
= extract_from_hash_table (directory
, file
);
667 g_assert (node
!= NULL
);
668 g_assert (node
->data
== file
);
670 /* Remove the item from the list. */
671 directory
->details
->file_list
= g_list_remove_link
672 (directory
->details
->file_list
, node
);
673 g_list_free_1 (node
);
675 nautilus_directory_remove_file_from_work_queue (directory
, file
);
677 if (!file
->details
->unconfirmed
) {
678 directory
->details
->confirmed_file_count
--;
681 /* Unref if we are monitoring. */
682 if (nautilus_directory_is_file_list_monitored (directory
)) {
683 nautilus_file_unref (file
);
687 #define NAUTILUS_DIRECTORY_FILE_LIST_DEFAULT_LIMIT 4000
690 nautilus_directory_file_list_length_reached (NautilusDirectory
*directory
)
692 static gboolean inited
= FALSE
;
693 static int directory_limit
= 0;
696 eel_preferences_add_auto_integer
697 ("/apps/nautilus/preferences/directory_limit",
701 if (directory_limit
< 0) { /* unlimited */
704 if (directory_limit
== 0) { /* dead gconfd */
705 directory_limit
= NAUTILUS_DIRECTORY_FILE_LIST_DEFAULT_LIMIT
;
708 return directory
->details
->confirmed_file_count
>= directory_limit
;
712 nautilus_directory_begin_file_name_change (NautilusDirectory
*directory
,
715 /* Find the list node in the hash table. */
716 return extract_from_hash_table (directory
, file
);
720 nautilus_directory_end_file_name_change (NautilusDirectory
*directory
,
724 /* Add the list node to the hash table. */
726 add_to_hash_table (directory
, file
, node
);
731 nautilus_directory_find_file_by_name (NautilusDirectory
*directory
,
736 g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory
), NULL
);
737 g_return_val_if_fail (name
!= NULL
, NULL
);
739 node
= g_hash_table_lookup (directory
->details
->file_hash
,
741 return node
== NULL
? NULL
: NAUTILUS_FILE (node
->data
);
744 /* "." for the directory-as-file, otherwise the filename */
746 nautilus_directory_find_file_by_internal_filename (NautilusDirectory
*directory
,
747 const char *internal_filename
)
749 NautilusFile
*result
;
751 if (eel_strcmp (internal_filename
, ".") == 0) {
752 result
= nautilus_directory_get_existing_corresponding_file (directory
);
753 if (result
!= NULL
) {
754 nautilus_file_unref (result
);
757 result
= nautilus_directory_find_file_by_name (directory
, internal_filename
);
764 nautilus_directory_emit_files_added (NautilusDirectory
*directory
,
767 if (added_files
!= NULL
) {
768 g_signal_emit (directory
,
769 signals
[FILES_ADDED
], 0,
775 nautilus_directory_emit_files_changed (NautilusDirectory
*directory
,
776 GList
*changed_files
)
778 if (changed_files
!= NULL
) {
779 g_signal_emit (directory
,
780 signals
[FILES_CHANGED
], 0,
786 nautilus_directory_emit_change_signals (NautilusDirectory
*directory
,
787 GList
*changed_files
)
791 for (p
= changed_files
; p
!= NULL
; p
= p
->next
) {
792 nautilus_file_emit_changed (p
->data
);
794 nautilus_directory_emit_files_changed (directory
, changed_files
);
798 nautilus_directory_emit_done_loading (NautilusDirectory
*directory
)
800 g_signal_emit (directory
,
801 signals
[DONE_LOADING
], 0);
805 nautilus_directory_emit_load_error (NautilusDirectory
*directory
,
808 g_signal_emit (directory
,
809 signals
[LOAD_ERROR
], 0,
813 /* Return a directory object for this one's parent. */
814 static NautilusDirectory
*
815 get_parent_directory (GFile
*location
)
817 NautilusDirectory
*directory
;
820 parent
= g_file_get_parent (location
);
822 directory
= nautilus_directory_get_internal (parent
, TRUE
);
823 g_object_unref (parent
);
829 /* If a directory object exists for this one's parent, then
830 * return it, otherwise return NULL.
832 static NautilusDirectory
*
833 get_parent_directory_if_exists (GFile
*location
)
835 NautilusDirectory
*directory
;
838 parent
= g_file_get_parent (location
);
840 directory
= nautilus_directory_get_internal (parent
, FALSE
);
841 g_object_unref (parent
);
848 hash_table_list_prepend (GHashTable
*table
, gconstpointer key
, gpointer data
)
852 list
= g_hash_table_lookup (table
, key
);
853 list
= g_list_prepend (list
, data
);
854 g_hash_table_insert (table
, (gpointer
) key
, list
);
858 call_files_added_free_list (gpointer key
, gpointer value
, gpointer user_data
)
860 g_assert (NAUTILUS_IS_DIRECTORY (key
));
861 g_assert (value
!= NULL
);
862 g_assert (user_data
== NULL
);
865 signals
[FILES_ADDED
], 0,
871 call_files_changed_common (NautilusDirectory
*directory
, GList
*file_list
)
876 for (node
= file_list
; node
!= NULL
; node
= node
->next
) {
878 if (file
->details
->directory
== directory
) {
879 nautilus_directory_add_file_to_work_queue (directory
,
883 nautilus_directory_async_state_changed (directory
);
884 nautilus_directory_emit_change_signals (directory
, file_list
);
888 call_files_changed_free_list (gpointer key
, gpointer value
, gpointer user_data
)
890 g_assert (value
!= NULL
);
891 g_assert (user_data
== NULL
);
893 call_files_changed_common (NAUTILUS_DIRECTORY (key
), value
);
898 call_files_changed_unref_free_list (gpointer key
, gpointer value
, gpointer user_data
)
900 g_assert (value
!= NULL
);
901 g_assert (user_data
== NULL
);
903 call_files_changed_common (NAUTILUS_DIRECTORY (key
), value
);
904 nautilus_file_list_free (value
);
908 call_get_file_info_free_list (gpointer key
, gpointer value
, gpointer user_data
)
910 NautilusDirectory
*directory
;
913 g_assert (NAUTILUS_IS_DIRECTORY (key
));
914 g_assert (value
!= NULL
);
915 g_assert (user_data
== NULL
);
920 nautilus_directory_get_info_for_new_files (directory
, files
);
921 g_list_foreach (files
, (GFunc
) g_object_unref
, NULL
);
926 invalidate_count_and_unref (gpointer key
, gpointer value
, gpointer user_data
)
928 g_assert (NAUTILUS_IS_DIRECTORY (key
));
929 g_assert (value
== key
);
930 g_assert (user_data
== NULL
);
932 nautilus_directory_invalidate_count_and_mime_list (key
);
933 nautilus_directory_unref (key
);
937 collect_parent_directories (GHashTable
*hash_table
, NautilusDirectory
*directory
)
939 g_assert (hash_table
!= NULL
);
940 g_assert (NAUTILUS_IS_DIRECTORY (directory
));
942 if (g_hash_table_lookup (hash_table
, directory
) == NULL
) {
943 nautilus_directory_ref (directory
);
944 g_hash_table_insert (hash_table
, directory
, directory
);
949 nautilus_directory_notify_files_added (GList
*files
)
951 GHashTable
*added_lists
;
953 NautilusDirectory
*directory
;
954 GHashTable
*parent_directories
;
956 GFile
*location
, *parent
;
958 /* Make a list of added files in each directory. */
959 added_lists
= g_hash_table_new (NULL
, NULL
);
961 /* Make a list of parent directories that will need their counts updated. */
962 parent_directories
= g_hash_table_new (NULL
, NULL
);
964 for (p
= files
; p
!= NULL
; p
= p
->next
) {
967 /* See if the directory is already known. */
968 directory
= get_parent_directory_if_exists (location
);
969 if (directory
== NULL
) {
970 /* In case the directory is not being
971 * monitored, but the corresponding file is,
972 * we must invalidate it's item count.
977 parent
= g_file_get_parent (location
);
979 file
= nautilus_file_get_existing (parent
);
980 g_object_unref (parent
);
984 nautilus_file_invalidate_count_and_mime_list (file
);
985 nautilus_file_unref (file
);
991 collect_parent_directories (parent_directories
, directory
);
993 /* If no one is monitoring files in the directory, nothing to do. */
994 if (!nautilus_directory_is_file_list_monitored (directory
)) {
995 nautilus_directory_unref (directory
);
999 file
= nautilus_file_get_existing (location
);
1000 /* We check is_added here, because the file could have been added
1001 * to the directory by a nautilus_file_get() but not gotten
1002 * files_added emitted
1004 if (file
&& file
->details
->is_added
) {
1005 /* A file already exists, it was probably renamed.
1006 * If it was renamed this could be ignored, but
1007 * queue a change just in case */
1008 nautilus_file_changed (file
);
1009 nautilus_file_unref (file
);
1011 hash_table_list_prepend (added_lists
,
1013 g_object_ref (location
));
1015 nautilus_directory_unref (directory
);
1018 /* Now get file info for the new files. This creates NautilusFile
1019 * objects for the new files, and sends out a files_added signal.
1021 g_hash_table_foreach (added_lists
, call_get_file_info_free_list
, NULL
);
1022 g_hash_table_destroy (added_lists
);
1024 /* Invalidate count for each parent directory. */
1025 g_hash_table_foreach (parent_directories
, invalidate_count_and_unref
, NULL
);
1026 g_hash_table_destroy (parent_directories
);
1030 uri_list_to_file_list (GList
*uris
)
1032 GList
*l
, *file_list
;
1039 for (l
= uris
; l
!= NULL
; l
= l
->next
) {
1041 file
= g_file_new_for_uri (uri
);
1042 file_list
= g_list_prepend (file_list
, file
);
1044 return g_list_reverse (file_list
);
1048 g_file_pair_free (GFilePair
*pair
)
1050 g_object_unref (pair
->to
);
1051 g_object_unref (pair
->from
);
1056 uri_pairs_to_file_pairs (GList
*uri_pairs
)
1058 GList
*l
, *file_pair_list
;
1059 GFilePair
*file_pair
;
1062 file_pair_list
= NULL
;
1064 for (l
= uri_pairs
; l
!= NULL
; l
= l
->next
) {
1066 file_pair
= g_new (GFilePair
, 1);
1067 file_pair
->from
= g_file_new_for_uri (uri_pair
->from_uri
);
1068 file_pair
->to
= g_file_new_for_uri (uri_pair
->to_uri
);
1070 file_pair_list
= g_list_prepend (file_pair_list
, file_pair
);
1072 return g_list_reverse (file_pair_list
);
1076 nautilus_directory_notify_files_added_by_uri (GList
*uris
)
1080 files
= uri_list_to_file_list (uris
);
1081 nautilus_directory_notify_files_added (files
);
1082 eel_g_object_list_free (files
);
1086 nautilus_directory_notify_files_changed (GList
*files
)
1088 GHashTable
*changed_lists
;
1093 /* Make a list of changed files in each directory. */
1094 changed_lists
= g_hash_table_new (NULL
, NULL
);
1096 /* Go through all the notifications. */
1097 for (node
= files
; node
!= NULL
; node
= node
->next
) {
1098 location
= node
->data
;
1100 /* Find the file. */
1101 file
= nautilus_file_get_existing (location
);
1103 /* Tell it to re-get info now, and later emit
1106 file
->details
->file_info_is_up_to_date
= FALSE
;
1107 file
->details
->top_left_text_is_up_to_date
= FALSE
;
1108 file
->details
->link_info_is_up_to_date
= FALSE
;
1109 nautilus_file_invalidate_extension_info_internal (file
);
1111 hash_table_list_prepend (changed_lists
,
1112 file
->details
->directory
,
1117 /* Now send out the changed signals. */
1118 g_hash_table_foreach (changed_lists
, call_files_changed_unref_free_list
, NULL
);
1119 g_hash_table_destroy (changed_lists
);
1123 nautilus_directory_notify_files_changed_by_uri (GList
*uris
)
1127 files
= uri_list_to_file_list (uris
);
1128 nautilus_directory_notify_files_changed (files
);
1129 eel_g_object_list_free (files
);
1133 nautilus_directory_notify_files_removed (GList
*files
)
1135 GHashTable
*changed_lists
;
1137 NautilusDirectory
*directory
;
1138 GHashTable
*parent_directories
;
1142 /* Make a list of changed files in each directory. */
1143 changed_lists
= g_hash_table_new (NULL
, NULL
);
1145 /* Make a list of parent directories that will need their counts updated. */
1146 parent_directories
= g_hash_table_new (NULL
, NULL
);
1148 /* Go through all the notifications. */
1149 for (p
= files
; p
!= NULL
; p
= p
->next
) {
1152 /* Update file count for parent directory if anyone might care. */
1153 directory
= get_parent_directory_if_exists (location
);
1154 if (directory
!= NULL
) {
1155 collect_parent_directories (parent_directories
, directory
);
1156 nautilus_directory_unref (directory
);
1159 /* Find the file. */
1160 file
= nautilus_file_get_existing (location
);
1161 if (file
!= NULL
&& !nautilus_file_rename_in_progress (file
)) {
1162 /* Mark it gone and prepare to send the changed signal. */
1163 nautilus_file_mark_gone (file
);
1164 hash_table_list_prepend (changed_lists
,
1165 file
->details
->directory
,
1166 nautilus_file_ref (file
));
1168 nautilus_file_unref (file
);
1171 /* Now send out the changed signals. */
1172 g_hash_table_foreach (changed_lists
, call_files_changed_unref_free_list
, NULL
);
1173 g_hash_table_destroy (changed_lists
);
1175 /* Invalidate count for each parent directory. */
1176 g_hash_table_foreach (parent_directories
, invalidate_count_and_unref
, NULL
);
1177 g_hash_table_destroy (parent_directories
);
1181 nautilus_directory_notify_files_removed_by_uri (GList
*uris
)
1185 files
= uri_list_to_file_list (uris
);
1186 nautilus_directory_notify_files_changed (files
);
1187 eel_g_object_list_free (files
);
1191 set_directory_location (NautilusDirectory
*directory
,
1194 if (directory
->details
->location
) {
1195 g_object_unref (directory
->details
->location
);
1197 directory
->details
->location
= g_object_ref (location
);
1202 change_directory_location (NautilusDirectory
*directory
,
1203 GFile
*new_location
)
1207 /* I believe it's impossible for a self-owned file/directory
1208 * to be moved. But if that did somehow happen, this function
1209 * wouldn't do enough to handle it.
1211 g_assert (directory
->details
->as_file
== NULL
);
1213 g_hash_table_remove (directories
,
1214 directory
->details
->location
);
1216 set_directory_location (directory
, new_location
);
1218 g_hash_table_insert (directories
,
1219 directory
->details
->location
,
1222 new_uri
= g_file_get_uri (new_location
);
1223 nautilus_directory_rename_directory_metadata (directory
, new_uri
);
1233 collect_directories_by_container (gpointer key
, gpointer value
, gpointer callback_data
)
1235 NautilusDirectory
*directory
;
1236 CollectData
*collect_data
;
1239 location
= (GFile
*) key
;
1240 directory
= NAUTILUS_DIRECTORY (value
);
1241 collect_data
= (CollectData
*) callback_data
;
1243 if (g_file_has_prefix (location
, collect_data
->container
) ||
1244 g_file_equal (collect_data
->container
, location
)) {
1245 nautilus_directory_ref (directory
);
1246 collect_data
->directories
=
1247 g_list_prepend (collect_data
->directories
,
1253 nautilus_directory_moved_internal (GFile
*old_location
,
1254 GFile
*new_location
)
1256 CollectData collection
;
1257 NautilusDirectory
*directory
;
1258 GList
*node
, *affected_files
;
1259 GFile
*new_directory_location
;
1260 char *relative_path
;
1262 collection
.container
= old_location
;
1263 collection
.directories
= NULL
;
1265 g_hash_table_foreach (directories
,
1266 collect_directories_by_container
,
1269 affected_files
= NULL
;
1271 for (node
= collection
.directories
; node
!= NULL
; node
= node
->next
) {
1272 directory
= NAUTILUS_DIRECTORY (node
->data
);
1273 new_directory_location
= NULL
;
1275 if (g_file_equal (directory
->details
->location
, old_location
)) {
1276 new_directory_location
= g_object_ref (new_location
);
1278 relative_path
= g_file_get_relative_path (old_location
,
1279 directory
->details
->location
);
1280 if (relative_path
!= NULL
) {
1281 new_directory_location
= g_file_resolve_relative_path (new_location
, relative_path
);
1282 g_free (relative_path
);
1287 if (new_directory_location
) {
1288 change_directory_location (directory
, new_directory_location
);
1289 g_object_unref (new_directory_location
);
1291 /* Collect affected files. */
1292 if (directory
->details
->as_file
!= NULL
) {
1293 affected_files
= g_list_prepend
1295 nautilus_file_ref (directory
->details
->as_file
));
1297 affected_files
= g_list_concat
1299 nautilus_file_list_copy (directory
->details
->file_list
));
1302 nautilus_directory_unref (directory
);
1305 g_list_free (collection
.directories
);
1307 return affected_files
;
1311 nautilus_directory_moved (const char *old_uri
,
1312 const char *new_uri
)
1317 GFile
*old_location
;
1318 GFile
*new_location
;
1320 hash
= g_hash_table_new (NULL
, NULL
);
1322 old_location
= g_file_new_for_uri (old_uri
);
1323 new_location
= g_file_new_for_uri (new_uri
);
1325 list
= nautilus_directory_moved_internal (old_location
, new_location
);
1326 for (node
= list
; node
!= NULL
; node
= node
->next
) {
1327 file
= NAUTILUS_FILE (node
->data
);
1328 hash_table_list_prepend (hash
,
1329 file
->details
->directory
,
1330 nautilus_file_ref (file
));
1332 nautilus_file_list_free (list
);
1334 g_object_unref (old_location
);
1335 g_object_unref (new_location
);
1337 g_hash_table_foreach (hash
, call_files_changed_unref_free_list
, NULL
);
1338 g_hash_table_destroy (hash
);
1342 nautilus_directory_notify_files_moved (GList
*file_pairs
)
1344 GList
*p
, *affected_files
, *node
;
1347 NautilusDirectory
*old_directory
, *new_directory
;
1348 GHashTable
*parent_directories
;
1349 GList
*new_files_list
, *unref_list
;
1350 GHashTable
*added_lists
, *changed_lists
;
1352 NautilusFileAttributes cancel_attributes
;
1353 GFile
*to_location
, *from_location
;
1355 /* Make a list of added and changed files in each directory. */
1356 new_files_list
= NULL
;
1357 added_lists
= g_hash_table_new (NULL
, NULL
);
1358 changed_lists
= g_hash_table_new (NULL
, NULL
);
1361 /* Make a list of parent directories that will need their counts updated. */
1362 parent_directories
= g_hash_table_new (NULL
, NULL
);
1364 cancel_attributes
= nautilus_file_get_all_attributes ();
1366 for (p
= file_pairs
; p
!= NULL
; p
= p
->next
) {
1368 from_location
= pair
->from
;
1369 to_location
= pair
->to
;
1371 /* Handle overwriting a file. */
1372 file
= nautilus_file_get_existing (to_location
);
1374 /* Mark it gone and prepare to send the changed signal. */
1375 nautilus_file_mark_gone (file
);
1376 new_directory
= file
->details
->directory
;
1377 hash_table_list_prepend (changed_lists
,
1380 collect_parent_directories (parent_directories
,
1384 /* Update any directory objects that are affected. */
1385 affected_files
= nautilus_directory_moved_internal (from_location
,
1387 for (node
= affected_files
; node
!= NULL
; node
= node
->next
) {
1388 file
= NAUTILUS_FILE (node
->data
);
1389 hash_table_list_prepend (changed_lists
,
1390 file
->details
->directory
,
1393 unref_list
= g_list_concat (unref_list
, affected_files
);
1395 /* Move an existing file. */
1396 file
= nautilus_file_get_existing (from_location
);
1398 /* Handle this as if it was a new file. */
1399 new_files_list
= g_list_prepend (new_files_list
,
1402 /* Handle notification in the old directory. */
1403 old_directory
= file
->details
->directory
;
1404 collect_parent_directories (parent_directories
, old_directory
);
1406 /* Cancel loading of attributes in the old directory */
1407 nautilus_directory_cancel_loading_file_attributes
1408 (old_directory
, file
, cancel_attributes
);
1410 /* Locate the new directory. */
1411 new_directory
= get_parent_directory (to_location
);
1412 collect_parent_directories (parent_directories
, new_directory
);
1413 /* We can unref now -- new_directory is in the
1414 * parent directories list so it will be
1415 * around until the end of this function
1418 nautilus_directory_unref (new_directory
);
1420 /* Update the file's name and directory. */
1421 name
= g_file_get_basename (to_location
);
1422 nautilus_file_update_name_and_directory
1423 (file
, name
, new_directory
);
1426 hash_table_list_prepend (changed_lists
,
1429 if (old_directory
!= new_directory
) {
1430 hash_table_list_prepend (added_lists
,
1435 /* Unref each file once to balance out nautilus_file_get_by_uri. */
1436 unref_list
= g_list_prepend (unref_list
, file
);
1440 /* Now send out the changed and added signals for existing file objects. */
1441 g_hash_table_foreach (changed_lists
, call_files_changed_free_list
, NULL
);
1442 g_hash_table_destroy (changed_lists
);
1443 g_hash_table_foreach (added_lists
, call_files_added_free_list
, NULL
);
1444 g_hash_table_destroy (added_lists
);
1446 /* Let the file objects go. */
1447 nautilus_file_list_free (unref_list
);
1449 /* Invalidate count for each parent directory. */
1450 g_hash_table_foreach (parent_directories
, invalidate_count_and_unref
, NULL
);
1451 g_hash_table_destroy (parent_directories
);
1453 /* Separate handling for brand new file objects. */
1454 nautilus_directory_notify_files_added (new_files_list
);
1455 g_list_free (new_files_list
);
1459 nautilus_directory_notify_files_moved_by_uri (GList
*uri_pairs
)
1463 file_pairs
= uri_pairs_to_file_pairs (uri_pairs
);
1464 nautilus_directory_notify_files_moved (file_pairs
);
1465 g_list_foreach (file_pairs
, (GFunc
)g_file_pair_free
, NULL
);
1466 g_list_free (file_pairs
);
1470 nautilus_directory_schedule_metadata_copy (GList
*file_pairs
)
1474 NautilusDirectory
*source_directory
, *destination_directory
;
1475 char *source_basename
, *destination_basename
;
1477 for (p
= file_pairs
; p
!= NULL
; p
= p
->next
) {
1480 source_directory
= get_parent_directory (pair
->from
);
1481 destination_directory
= get_parent_directory (pair
->to
);
1483 source_basename
= g_file_get_basename (pair
->from
);
1484 destination_basename
= g_file_get_basename (pair
->to
);
1486 if (source_directory
!= NULL
&& destination_directory
!= NULL
) {
1487 nautilus_directory_copy_file_metadata (source_directory
,
1489 destination_directory
,
1490 destination_basename
);
1493 g_free (source_basename
);
1494 g_free (destination_basename
);
1496 nautilus_directory_unref (source_directory
);
1497 nautilus_directory_unref (destination_directory
);
1502 nautilus_directory_schedule_metadata_copy_by_uri (GList
*uri_pairs
)
1506 file_pairs
= uri_pairs_to_file_pairs (uri_pairs
);
1507 nautilus_directory_schedule_metadata_copy (file_pairs
);
1508 g_list_foreach (file_pairs
, (GFunc
)g_file_pair_free
, NULL
);
1509 g_list_free (file_pairs
);
1514 nautilus_directory_schedule_metadata_move (GList
*file_pairs
)
1518 NautilusDirectory
*source_directory
, *destination_directory
;
1519 char *source_basename
, *destination_basename
;
1521 for (p
= file_pairs
; p
!= NULL
; p
= p
->next
) {
1524 source_directory
= get_parent_directory (pair
->from
);
1525 destination_directory
= get_parent_directory (pair
->to
);
1527 source_basename
= g_file_get_basename (pair
->from
);
1528 destination_basename
= g_file_get_basename (pair
->to
);
1530 nautilus_directory_copy_file_metadata (source_directory
,
1532 destination_directory
,
1533 destination_basename
);
1534 nautilus_directory_remove_file_metadata (source_directory
,
1537 g_free (source_basename
);
1538 g_free (destination_basename
);
1540 nautilus_directory_unref (source_directory
);
1541 nautilus_directory_unref (destination_directory
);
1546 nautilus_directory_schedule_metadata_move_by_uri (GList
*uri_pairs
)
1550 file_pairs
= uri_pairs_to_file_pairs (uri_pairs
);
1551 nautilus_directory_schedule_metadata_move (file_pairs
);
1552 g_list_foreach (file_pairs
, (GFunc
)g_file_pair_free
, NULL
);
1553 g_list_free (file_pairs
);
1557 nautilus_directory_schedule_metadata_remove (GList
*files
)
1560 NautilusDirectory
*directory
;
1564 for (p
= files
; p
!= NULL
; p
= p
->next
) {
1567 directory
= get_parent_directory (location
);
1569 basename
= g_file_get_basename (location
);
1570 nautilus_directory_remove_file_metadata (directory
, basename
);
1574 nautilus_directory_unref (directory
);
1579 nautilus_directory_schedule_metadata_remove_by_uri (GList
*uris
)
1583 files
= uri_list_to_file_list (uris
);
1584 nautilus_directory_schedule_metadata_remove (files
);
1585 eel_g_object_list_free (files
);
1589 nautilus_directory_schedule_position_set (GList
*position_setting_list
)
1592 const NautilusFileChangesQueuePosition
*item
;
1596 for (p
= position_setting_list
; p
!= NULL
; p
= p
->next
) {
1597 item
= (NautilusFileChangesQueuePosition
*) p
->data
;
1599 file
= nautilus_file_get (item
->location
);
1602 g_snprintf (str
, sizeof (str
), "%d,%d", item
->point
.x
, item
->point
.y
);
1606 nautilus_file_set_metadata
1608 NAUTILUS_METADATA_KEY_ICON_POSITION
,
1613 g_snprintf (str
, sizeof (str
), "%d", item
->screen
);
1617 nautilus_file_set_metadata
1619 NAUTILUS_METADATA_KEY_SCREEN
,
1623 nautilus_file_unref (file
);
1628 nautilus_directory_contains_file (NautilusDirectory
*directory
,
1631 g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory
), FALSE
);
1632 g_return_val_if_fail (NAUTILUS_IS_FILE (file
), FALSE
);
1634 if (nautilus_file_is_gone (file
)) {
1638 return EEL_CALL_METHOD_WITH_RETURN_VALUE
1639 (NAUTILUS_DIRECTORY_CLASS
, directory
,
1640 contains_file
, (directory
, file
));
1644 nautilus_directory_get_file_uri (NautilusDirectory
*directory
,
1645 const char *file_name
)
1650 g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory
), NULL
);
1651 g_return_val_if_fail (file_name
!= NULL
, NULL
);
1655 child
= g_file_get_child (directory
->details
->location
, file_name
);
1656 result
= g_file_get_uri (child
);
1657 g_object_unref (child
);
1663 nautilus_directory_call_when_ready (NautilusDirectory
*directory
,
1664 NautilusFileAttributes file_attributes
,
1665 gboolean wait_for_all_files
,
1666 NautilusDirectoryCallback callback
,
1667 gpointer callback_data
)
1669 g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory
));
1670 g_return_if_fail (callback
!= NULL
);
1673 (NAUTILUS_DIRECTORY_CLASS
, directory
,
1674 call_when_ready
, (directory
, file_attributes
, wait_for_all_files
,
1675 callback
, callback_data
));
1679 nautilus_directory_cancel_callback (NautilusDirectory
*directory
,
1680 NautilusDirectoryCallback callback
,
1681 gpointer callback_data
)
1683 g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory
));
1684 g_return_if_fail (callback
!= NULL
);
1687 (NAUTILUS_DIRECTORY_CLASS
, directory
,
1688 cancel_callback
, (directory
, callback
, callback_data
));
1692 nautilus_directory_file_monitor_add (NautilusDirectory
*directory
,
1693 gconstpointer client
,
1694 gboolean monitor_hidden_files
,
1695 gboolean monitor_backup_files
,
1696 NautilusFileAttributes file_attributes
,
1697 NautilusDirectoryCallback callback
,
1698 gpointer callback_data
)
1700 g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory
));
1701 g_return_if_fail (client
!= NULL
);
1704 (NAUTILUS_DIRECTORY_CLASS
, directory
,
1705 file_monitor_add
, (directory
, client
,
1706 monitor_hidden_files
,
1707 monitor_backup_files
,
1709 callback
, callback_data
));
1713 nautilus_directory_file_monitor_remove (NautilusDirectory
*directory
,
1714 gconstpointer client
)
1716 g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory
));
1717 g_return_if_fail (client
!= NULL
);
1720 (NAUTILUS_DIRECTORY_CLASS
, directory
,
1721 file_monitor_remove
, (directory
, client
));
1725 nautilus_directory_force_reload (NautilusDirectory
*directory
)
1727 g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory
));
1730 (NAUTILUS_DIRECTORY_CLASS
, directory
,
1731 force_reload
, (directory
));
1735 nautilus_directory_is_not_empty (NautilusDirectory
*directory
)
1737 g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory
), FALSE
);
1739 return EEL_CALL_METHOD_WITH_RETURN_VALUE
1740 (NAUTILUS_DIRECTORY_CLASS
, directory
,
1741 is_not_empty
, (directory
));
1745 is_tentative (gpointer data
, gpointer callback_data
)
1749 g_assert (callback_data
== NULL
);
1751 file
= NAUTILUS_FILE (data
);
1752 /* Avoid returning files with !is_added, because these
1753 * will later be sent with the files_added signal, and a
1754 * user doing get_file_list + files_added monitoring will
1755 * then see the file twice */
1756 return !file
->details
->got_file_info
|| !file
->details
->is_added
;
1760 nautilus_directory_get_file_list (NautilusDirectory
*directory
)
1762 return EEL_CALL_METHOD_WITH_RETURN_VALUE
1763 (NAUTILUS_DIRECTORY_CLASS
, directory
,
1764 get_file_list
, (directory
));
1768 real_get_file_list (NautilusDirectory
*directory
)
1770 GList
*tentative_files
, *non_tentative_files
;
1772 tentative_files
= eel_g_list_partition
1773 (g_list_copy (directory
->details
->file_list
),
1774 is_tentative
, NULL
, &non_tentative_files
);
1775 g_list_free (tentative_files
);
1777 nautilus_file_list_ref (non_tentative_files
);
1778 return non_tentative_files
;
1782 real_is_editable (NautilusDirectory
*directory
)
1788 nautilus_directory_is_editable (NautilusDirectory
*directory
)
1790 return EEL_CALL_METHOD_WITH_RETURN_VALUE
1791 (NAUTILUS_DIRECTORY_CLASS
, directory
,
1792 is_editable
, (directory
));
1796 nautilus_directory_match_pattern (NautilusDirectory
*directory
, const char *pattern
)
1798 GList
*files
, *l
, *ret
;
1803 spec
= g_pattern_spec_new (pattern
);
1805 files
= nautilus_directory_get_file_list (directory
);
1806 for (l
= files
; l
; l
= l
->next
) {
1810 file
= NAUTILUS_FILE (l
->data
);
1811 name
= nautilus_file_get_display_name (file
);
1813 if (g_pattern_match_string (spec
, name
)) {
1814 ret
= g_list_prepend(ret
, nautilus_file_ref (file
));
1820 g_pattern_spec_free (spec
);
1821 nautilus_file_list_free (files
);
1827 * nautilus_directory_list_ref
1829 * Ref all the directories in a list.
1830 * @list: GList of directories.
1833 nautilus_directory_list_ref (GList
*list
)
1835 g_list_foreach (list
, (GFunc
) nautilus_directory_ref
, NULL
);
1840 * nautilus_directory_list_unref
1842 * Unref all the directories in a list.
1843 * @list: GList of directories.
1846 nautilus_directory_list_unref (GList
*list
)
1848 g_list_foreach (list
, (GFunc
) nautilus_directory_unref
, NULL
);
1852 * nautilus_directory_list_free
1854 * Free a list of directories after unrefing them.
1855 * @list: GList of directories.
1858 nautilus_directory_list_free (GList
*list
)
1860 nautilus_directory_list_unref (list
);
1865 * nautilus_directory_list_copy
1867 * Copy the list of directories, making a new ref of each,
1868 * @list: GList of directories.
1871 nautilus_directory_list_copy (GList
*list
)
1873 return g_list_copy (nautilus_directory_list_ref (list
));
1877 compare_by_uri (NautilusDirectory
*a
, NautilusDirectory
*b
)
1879 char *uri_a
, *uri_b
;
1882 uri_a
= g_file_get_uri (a
->details
->location
);
1883 uri_b
= g_file_get_uri (b
->details
->location
);
1885 res
= strcmp (uri_a
, uri_b
);
1894 compare_by_uri_cover (gconstpointer a
, gconstpointer b
)
1896 return compare_by_uri (NAUTILUS_DIRECTORY (a
), NAUTILUS_DIRECTORY (b
));
1900 * nautilus_directory_list_sort_by_uri
1902 * Sort the list of directories by directory uri.
1903 * @list: GList of directories.
1906 nautilus_directory_list_sort_by_uri (GList
*list
)
1908 return g_list_sort (list
, compare_by_uri_cover
);
1912 nautilus_directory_is_desktop_directory (NautilusDirectory
*directory
)
1914 if (directory
->details
->location
== NULL
) {
1918 return nautilus_is_desktop_directory (directory
->details
->location
);
1921 #if !defined (NAUTILUS_OMIT_SELF_CHECK)
1923 #include <eel/eel-debug.h>
1924 #include "nautilus-file-attributes.h"
1926 static int data_dummy
;
1927 static gboolean got_metadata_flag
;
1928 static gboolean got_files_flag
;
1931 got_metadata_callback (NautilusDirectory
*directory
, GList
*files
, gpointer callback_data
)
1933 g_assert (NAUTILUS_IS_DIRECTORY (directory
));
1934 g_assert (callback_data
== &data_dummy
);
1936 got_metadata_flag
= TRUE
;
1940 got_files_callback (NautilusDirectory
*directory
, GList
*files
, gpointer callback_data
)
1942 g_assert (NAUTILUS_IS_DIRECTORY (directory
));
1943 g_assert (g_list_length (files
) > 10);
1944 g_assert (callback_data
== &data_dummy
);
1946 got_files_flag
= TRUE
;
1949 /* Return the number of extant NautilusDirectories */
1951 nautilus_directory_number_outstanding (void)
1953 return directories
? g_hash_table_size (directories
) : 0;
1957 nautilus_self_check_directory (void)
1959 NautilusDirectory
*directory
;
1962 directory
= nautilus_directory_get_by_uri ("file:///etc");
1963 file
= nautilus_file_get_by_uri ("file:///etc/passwd");
1965 EEL_CHECK_INTEGER_RESULT (g_hash_table_size (directories
), 1);
1967 nautilus_directory_file_monitor_add
1968 (directory
, &data_dummy
,
1969 TRUE
, TRUE
, 0, NULL
, NULL
);
1971 got_metadata_flag
= FALSE
;
1973 nautilus_directory_call_when_ready (directory
, NAUTILUS_FILE_ATTRIBUTE_METADATA
, TRUE
,
1974 got_metadata_callback
, &data_dummy
);
1976 while (!got_metadata_flag
) {
1977 gtk_main_iteration ();
1980 nautilus_file_set_metadata (file
, "test", "default", "value");
1981 EEL_CHECK_STRING_RESULT (nautilus_file_get_metadata (file
, "test", "default"), "value");
1983 nautilus_file_set_boolean_metadata (file
, "test_boolean", TRUE
, TRUE
);
1984 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_get_boolean_metadata (file
, "test_boolean", TRUE
), TRUE
);
1985 nautilus_file_set_boolean_metadata (file
, "test_boolean", TRUE
, FALSE
);
1986 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_get_boolean_metadata (file
, "test_boolean", TRUE
), FALSE
);
1987 EEL_CHECK_BOOLEAN_RESULT (nautilus_file_get_boolean_metadata (NULL
, "test_boolean", TRUE
), TRUE
);
1989 nautilus_file_set_integer_metadata (file
, "test_integer", 0, 17);
1990 EEL_CHECK_INTEGER_RESULT (nautilus_file_get_integer_metadata (file
, "test_integer", 0), 17);
1991 nautilus_file_set_integer_metadata (file
, "test_integer", 0, -1);
1992 EEL_CHECK_INTEGER_RESULT (nautilus_file_get_integer_metadata (file
, "test_integer", 0), -1);
1993 nautilus_file_set_integer_metadata (file
, "test_integer", 42, 42);
1994 EEL_CHECK_INTEGER_RESULT (nautilus_file_get_integer_metadata (file
, "test_integer", 42), 42);
1995 EEL_CHECK_INTEGER_RESULT (nautilus_file_get_integer_metadata (NULL
, "test_integer", 42), 42);
1996 EEL_CHECK_INTEGER_RESULT (nautilus_file_get_integer_metadata (file
, "nonexistent_key", 42), 42);
1998 EEL_CHECK_BOOLEAN_RESULT (nautilus_directory_get_by_uri ("file:///etc") == directory
, TRUE
);
1999 nautilus_directory_unref (directory
);
2001 EEL_CHECK_BOOLEAN_RESULT (nautilus_directory_get_by_uri ("file:///etc/") == directory
, TRUE
);
2002 nautilus_directory_unref (directory
);
2004 EEL_CHECK_BOOLEAN_RESULT (nautilus_directory_get_by_uri ("file:///etc////") == directory
, TRUE
);
2005 nautilus_directory_unref (directory
);
2007 nautilus_file_unref (file
);
2009 nautilus_directory_file_monitor_remove (directory
, &data_dummy
);
2011 nautilus_directory_unref (directory
);
2013 while (g_hash_table_size (directories
) != 0) {
2014 gtk_main_iteration ();
2017 EEL_CHECK_INTEGER_RESULT (g_hash_table_size (directories
), 0);
2019 directory
= nautilus_directory_get_by_uri ("file:///etc");
2021 got_metadata_flag
= FALSE
;
2022 nautilus_directory_call_when_ready (directory
, NAUTILUS_FILE_ATTRIBUTE_METADATA
, TRUE
,
2023 got_metadata_callback
, &data_dummy
);
2025 while (!got_metadata_flag
) {
2026 gtk_main_iteration ();
2029 EEL_CHECK_BOOLEAN_RESULT (nautilus_directory_is_metadata_read (directory
), TRUE
);
2031 got_files_flag
= FALSE
;
2033 nautilus_directory_call_when_ready (directory
,
2034 NAUTILUS_FILE_ATTRIBUTE_INFO
|
2035 NAUTILUS_FILE_ATTRIBUTE_DEEP_COUNTS
,
2037 got_files_callback
, &data_dummy
);
2039 while (!got_files_flag
) {
2040 gtk_main_iteration ();
2043 EEL_CHECK_BOOLEAN_RESULT (directory
->details
->file_list
== NULL
, TRUE
);
2045 EEL_CHECK_INTEGER_RESULT (g_hash_table_size (directories
), 1);
2047 file
= nautilus_file_get_by_uri ("file:///etc/passwd");
2049 EEL_CHECK_STRING_RESULT (nautilus_file_get_metadata (file
, "test", "default"), "value");
2051 nautilus_file_unref (file
);
2053 nautilus_directory_unref (directory
);
2055 EEL_CHECK_INTEGER_RESULT (g_hash_table_size (directories
), 0);
2058 #endif /* !NAUTILUS_OMIT_SELF_CHECK */