From 3bb72b2e4bf0cf966f34cf3073bd0284e40073c0 Mon Sep 17 00:00:00 2001 From: Darin Adler Date: Thu, 27 Apr 2000 01:20:35 +0000 Subject: Implemented async. lookup of information about newly arrived files. * libnautilus-extensions/nautilus-directory-async.c (nautilus_directory_schedule_dequeue_pending_idle), (new_files_callback), (nautilus_directory_get_info_for_new_files): * libnautilus-extensions/nautilus-directory-private.h: * libnautilus-extensions/nautilus-directory.c (call_files_added), (call_files_added_free_list) (call_files_changed), (call_fiels_changed_free_list), (call_get_file_info_free_list), (nautilus_directory_notify_files_added), (nautilus_directory_notify_files_removed), (nautilus_directory_notify_files_moved): Implemented async. lookup of information about newly arrived files. Changed moved files to work without a new call to get file information. Fixed some storage leaks. * libnautilus-extensions/nautilus-directory-async.c (empty_close_callback), (metafile_read_close), (nautilus_metafile_read_cancel), (metafile_read_callback), (metafile_read_some), (metafile_read_open_callback), (metafile_write_callback): Fixed bug where we were not closing files when cancelling. This requires a bug fix in GNOME VFS to be effective. * libnautilus-extensions/nautilus-directory-async.c (dequeue_pending_idle_callback): * libnautilus-extensions/nautilus-directory-private.h: * libnautilus-extensions/nautilus-directory.c (nautilus_directory_destroy): Use new functions in GNOME VFS instead of our own. * components/html/ntl-web-browser.c (main): Fixed a warning. * docs/nautilus.faq: Tweak. --- ChangeLog | 35 ++++- components/html/ntl-web-browser.c | 1 - docs/nautilus.faq | 3 - libnautilus-extensions/nautilus-directory-async.c | 112 +++++++++++----- .../nautilus-directory-private.h | 9 +- libnautilus-extensions/nautilus-directory.c | 147 +++++++++++---------- libnautilus-private/nautilus-directory-async.c | 112 +++++++++++----- libnautilus-private/nautilus-directory-private.h | 9 +- libnautilus-private/nautilus-directory.c | 147 +++++++++++---------- 9 files changed, 360 insertions(+), 215 deletions(-) diff --git a/ChangeLog b/ChangeLog index cb4e20ae6..aa7b9db95 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,37 @@ +2000-04-26 Darin Adler + + * libnautilus-extensions/nautilus-directory-async.c + (nautilus_directory_schedule_dequeue_pending_idle), + (new_files_callback), (nautilus_directory_get_info_for_new_files): + * libnautilus-extensions/nautilus-directory-private.h: + * libnautilus-extensions/nautilus-directory.c (call_files_added), + (call_files_added_free_list) (call_files_changed), + (call_fiels_changed_free_list), (call_get_file_info_free_list), + (nautilus_directory_notify_files_added), + (nautilus_directory_notify_files_removed), + (nautilus_directory_notify_files_moved): + Implemented async. lookup of information about newly arrived + files. Changed moved files to work without a new call to get + file information. Fixed some storage leaks. + + * libnautilus-extensions/nautilus-directory-async.c + (empty_close_callback), (metafile_read_close), + (nautilus_metafile_read_cancel), (metafile_read_callback), + (metafile_read_some), (metafile_read_open_callback), + (metafile_write_callback): Fixed bug where we were not closing + files when cancelling. This requires a bug fix in GNOME VFS to be + effective. + + * libnautilus-extensions/nautilus-directory-async.c + (dequeue_pending_idle_callback): + * libnautilus-extensions/nautilus-directory-private.h: + * libnautilus-extensions/nautilus-directory.c + (nautilus_directory_destroy): + Use new functions in GNOME VFS instead of our own. + + * components/html/ntl-web-browser.c (main): Fixed a warning. + * docs/nautilus.faq: Tweak. + 2000-04-26 John Sullivan More FIXME-to-bug work. @@ -878,7 +912,6 @@ * libnautilus-extensions/nautilus-directory.c: (nautilus_directory_notify_files_moved): - Darin helped me finish implementing the missing parts of the call, including updating the reference to the new directory object, updating the file info structure to match the file's new location. diff --git a/components/html/ntl-web-browser.c b/components/html/ntl-web-browser.c index 630e45482..b97fda4db 100644 --- a/components/html/ntl-web-browser.c +++ b/components/html/ntl-web-browser.c @@ -615,7 +615,6 @@ int main(int argc, char *argv[]) { BonoboGenericFactory *factory; CORBA_ORB orb; - CORBA_Environment ev; if (getenv("NAUTILUS_DEBUG") != NULL) nautilus_make_warnings_and_criticals_stop_in_debugger diff --git a/docs/nautilus.faq b/docs/nautilus.faq index c30fb2948..7719c6e3a 100644 --- a/docs/nautilus.faq +++ b/docs/nautilus.faq @@ -9,6 +9,3 @@ 2. What are some useful nautilus resources ? See http://nautilus.eazel.com/ - - - diff --git a/libnautilus-extensions/nautilus-directory-async.c b/libnautilus-extensions/nautilus-directory-async.c index 15975ff61..cce2eff91 100644 --- a/libnautilus-extensions/nautilus-directory-async.c +++ b/libnautilus-extensions/nautilus-directory-async.c @@ -44,6 +44,7 @@ struct MetafileReadState { GnomeVFSAsyncHandle *handle; + gboolean is_open; gpointer buffer; size_t bytes_read; }; @@ -69,9 +70,6 @@ static void directory_load_done GnomeVFSResult result); static void directory_load_one (NautilusDirectory *directory, GnomeVFSFileInfo *info); -static void metafile_close_callback (GnomeVFSAsyncHandle *handle, - GnomeVFSResult result, - gpointer callback_data); static void metafile_read_callback (GnomeVFSAsyncHandle *handle, GnomeVFSResult result, gpointer buffer, @@ -100,6 +98,27 @@ static GnomeVFSDirectoryListPosition nautilus_gnome_vfs_directory_list_get_next_ GnomeVFSDirectoryListPosition position); static void process_pending_file_attribute_requests (NautilusDirectory *directory); +static void +empty_close_callback (GnomeVFSAsyncHandle *handle, + GnomeVFSResult result, + gpointer callback_data) +{ + /* Do nothing. */ +} + +static void +metafile_read_close (NautilusDirectory *directory) +{ + g_assert (directory->details->read_state->handle != NULL); + if (directory->details->read_state->is_open) { + gnome_vfs_async_close (directory->details->read_state->handle, + empty_close_callback, + directory); + directory->details->read_state->is_open = TRUE; + } + directory->details->read_state->handle = NULL; +} + static void metafile_read_done (NautilusDirectory *directory) { @@ -132,7 +151,9 @@ nautilus_metafile_read_cancel (NautilusDirectory *directory) return; } + g_assert (directory->details->read_state->handle != NULL); gnome_vfs_async_cancel (directory->details->read_state->handle); + metafile_read_close (directory); g_free (directory->details->read_state); directory->details->read_state = NULL; } @@ -194,14 +215,6 @@ metafile_read_complete (NautilusDirectory *directory) metafile_read_done (directory); } -static void -metafile_close_callback (GnomeVFSAsyncHandle *handle, - GnomeVFSResult result, - gpointer callback_data) -{ - /* Do nothing. */ -} - static void metafile_read_callback (GnomeVFSAsyncHandle *handle, GnomeVFSResult result, @@ -221,6 +234,7 @@ metafile_read_callback (GnomeVFSAsyncHandle *handle, if (result != GNOME_VFS_OK && result != GNOME_VFS_ERROR_EOF) { + metafile_read_close (directory); metafile_read_failed (directory, result); return; } @@ -236,10 +250,7 @@ metafile_read_callback (GnomeVFSAsyncHandle *handle, return; } - gnome_vfs_async_close (directory->details->read_state->handle, - metafile_close_callback, - directory); - + metafile_read_close (directory); metafile_read_complete (directory); } @@ -273,6 +284,7 @@ metafile_read_open_callback (GnomeVFSAsyncHandle *handle, return; } + directory->details->read_state->is_open = TRUE; metafile_read_some (directory); } @@ -356,15 +368,17 @@ metafile_write_callback (GnomeVFSAsyncHandle *handle, g_assert (directory->details->write_state->buffer == buffer); g_assert (directory->details->write_state->size == bytes_requested); + g_assert (directory->details->write_state->handle != NULL); + gnome_vfs_async_close (directory->details->write_state->handle, + empty_close_callback, + directory); + directory->details->write_state->handle = NULL; + if (result != GNOME_VFS_OK) { metafile_write_failed (directory, result); return; } - gnome_vfs_async_close (directory->details->write_state->handle, - metafile_close_callback, - directory); - metafile_write_complete (directory); } @@ -751,7 +765,7 @@ dequeue_pending_idle_callback (gpointer callback_data) /* If we stopped monitoring, then throw away these. */ if (!nautilus_directory_is_file_list_monitored (directory)) { - nautilus_gnome_vfs_file_info_list_free (pending_file_info); + gnome_vfs_file_info_list_free (pending_file_info); return FALSE; } @@ -775,7 +789,7 @@ dequeue_pending_idle_callback (gpointer callback_data) pending_files = g_list_prepend (pending_files, file); } } - nautilus_gnome_vfs_file_info_list_free (pending_file_info); + gnome_vfs_file_info_list_free (pending_file_info); /* Tell the objects that are monitoring about these new files. */ nautilus_directory_emit_files_added (directory, pending_files); @@ -801,8 +815,11 @@ nautilus_directory_schedule_dequeue_pending (NautilusDirectory *directory) static void directory_load_one (NautilusDirectory *directory, - GnomeVFSFileInfo *info) + GnomeVFSFileInfo *info) { + if (info == NULL) { + return; + } gnome_vfs_file_info_ref (info); directory->details->pending_file_info = g_list_prepend (directory->details->pending_file_info, info); @@ -838,10 +855,10 @@ nautilus_gnome_vfs_directory_list_get_next_position (GnomeVFSDirectoryList *list static void directory_load_callback (GnomeVFSAsyncHandle *handle, - GnomeVFSResult result, - GnomeVFSDirectoryList *list, - guint entries_read, - gpointer callback_data) + GnomeVFSResult result, + GnomeVFSDirectoryList *list, + guint entries_read, + gpointer callback_data) { NautilusDirectory *directory; GnomeVFSDirectoryListPosition last_handled, p; @@ -1149,15 +1166,46 @@ process_pending_file_attribute_requests (NautilusDirectory *directory) g_free (uri); } -void -nautilus_gnome_vfs_file_info_list_unref (GList *list) +static void +new_files_callback (GnomeVFSAsyncHandle *handle, + GList *results, + gpointer callback_data) { - g_list_foreach (list, (GFunc) gnome_vfs_file_info_unref, NULL); + GList **handles, *p; + NautilusDirectory *directory; + GnomeVFSGetFileInfoResult *result; + + directory = NAUTILUS_DIRECTORY (callback_data); + handles = &directory->details->get_file_infos_in_progress; + g_assert (handle == NULL || g_list_find (*handles, handle) != NULL); + + /* Note that this call is done. */ + *handles = g_list_remove (*handles, handle); + + /* Queue up the new files. */ + for (p = results; p != NULL; p = p->next) { + result = p->data; + directory_load_one (directory, result->file_info); + } } void -nautilus_gnome_vfs_file_info_list_free (GList *list) +nautilus_directory_get_info_for_new_files (NautilusDirectory *directory, + GList *vfs_uri_list) { - nautilus_gnome_vfs_file_info_list_unref (list); - g_list_free (list); + GnomeVFSAsyncHandle *handle; + + gnome_vfs_async_get_file_info + (&handle, + vfs_uri_list, + (GNOME_VFS_FILE_INFO_GETMIMETYPE + | GNOME_VFS_FILE_INFO_FASTMIMETYPE + | GNOME_VFS_FILE_INFO_FOLLOWLINKS), + NULL, + new_files_callback, + directory); + + directory->details->get_file_infos_in_progress + = g_list_prepend (directory->details->get_file_infos_in_progress, + handle); } diff --git a/libnautilus-extensions/nautilus-directory-private.h b/libnautilus-extensions/nautilus-directory-private.h index a81263a4f..e6f88f640 100644 --- a/libnautilus-extensions/nautilus-directory-private.h +++ b/libnautilus-extensions/nautilus-directory-private.h @@ -65,9 +65,12 @@ struct NautilusDirectoryDetails gboolean directory_loaded; GnomeVFSAsyncHandle *directory_load_in_progress; GnomeVFSDirectoryListPosition directory_load_list_last_handled; - GList *pending_file_info; + + GList *pending_file_info; /* list of GnomeVFSFileInfo */ guint dequeue_pending_idle_id; + GList *get_file_infos_in_progress; /* list of GnomeVFSAsyncHandle* */ + GnomeVFSAsyncHandle *count_in_progress; NautilusFile *count_file; }; @@ -112,6 +115,8 @@ void nautilus_directory_file_monitor_add_internal (NautilusDirectory void nautilus_directory_file_monitor_remove_internal (NautilusDirectory *directory, NautilusFile *file, gconstpointer client); +void nautilus_directory_get_info_for_new_files (NautilusDirectory *directory, + GList *vfs_uris); gboolean nautilus_directory_is_file_list_monitored (NautilusDirectory *directory); void nautilus_directory_remove_file_monitor_link (NautilusDirectory *directory, GList *link); @@ -149,5 +154,3 @@ int nautilus_directory_number_outstanding (void); /* Shared functions not directly related to NautilusDirectory/File. */ int nautilus_compare_file_with_name (gconstpointer a, gconstpointer b); -void nautilus_gnome_vfs_file_info_list_free (GList *list); -void nautilus_gnome_vfs_file_info_list_unref (GList *list); diff --git a/libnautilus-extensions/nautilus-directory.c b/libnautilus-extensions/nautilus-directory.c index 8fa42ffa8..e84880968 100644 --- a/libnautilus-extensions/nautilus-directory.c +++ b/libnautilus-extensions/nautilus-directory.c @@ -154,6 +154,7 @@ nautilus_directory_destroy (GtkObject *object) g_assert (directory->details->write_state == NULL); nautilus_metafile_read_cancel (directory); + g_assert (directory->details->read_state == NULL); if (nautilus_directory_is_file_list_monitored (directory)) { nautilus_directory_stop_monitoring_file_list (directory); @@ -185,7 +186,7 @@ nautilus_directory_destroy (GtkObject *object) g_assert (directory->details->directory_load_in_progress == NULL); g_assert (directory->details->count_in_progress == NULL); g_assert (directory->details->dequeue_pending_idle_id == 0); - nautilus_gnome_vfs_file_info_list_unref (directory->details->pending_file_info); + gnome_vfs_file_info_list_unref (directory->details->pending_file_info); g_assert (directory->details->write_metafile_idle_id == 0); g_free (directory->details); @@ -852,50 +853,18 @@ get_file_if_exists (const char *uri) return file; } -void -nautilus_directory_notify_files_added (GList *uris) +static void +hash_table_list_prepend (GHashTable *table, gconstpointer key, gpointer data) { - GList *p; - NautilusDirectory *directory; - GnomeVFSFileInfo *info; - const char *uri; - GnomeVFSResult result; - - /* FIXME bugzilla.eazel.com 465: - gnome_vfs_file_info calls need to be - called asynchronously. We probably need a new gnome_vfs call that - takes a list of URIs and generates a list of file info structures. - */ - for (p = uris; p != NULL; p = p->next) { - uri = (const char *) p->data; - - /* See if the directory is already known. */ - directory = get_parent_directory_if_exists (uri); - if (directory == NULL) { - continue; - } - - /* If no one is monitoring files in the directory, nothing to do. */ - if (!nautilus_directory_is_file_list_monitored (directory)) { - continue; - } + GList *list; - info = gnome_vfs_file_info_new (); - result = gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_DEFAULT, NULL); - if (result == GNOME_VFS_OK) { - gnome_vfs_file_info_ref (info); - directory->details->pending_file_info - = g_list_prepend (directory->details->pending_file_info, info); - - nautilus_directory_schedule_dequeue_pending (directory); - } - - gnome_vfs_file_info_unref (info); - } + list = g_hash_table_lookup (table, key); + list = g_list_prepend (list, data); + g_hash_table_insert (table, (gpointer) key, list); } static void -call_files_added (gpointer key, gpointer value, gpointer user_data) +call_files_added_free_list (gpointer key, gpointer value, gpointer user_data) { g_assert (NAUTILUS_IS_DIRECTORY (key)); g_assert (value != NULL); @@ -904,26 +873,70 @@ call_files_added (gpointer key, gpointer value, gpointer user_data) gtk_signal_emit (GTK_OBJECT (key), signals[FILES_ADDED], value); + g_list_free (value); } static void -call_files_changed (gpointer key, gpointer value, gpointer user_data) +call_files_changed_free_list (gpointer key, gpointer value, gpointer user_data) { g_assert (NAUTILUS_IS_DIRECTORY (key)); g_assert (value != NULL); g_assert (user_data == NULL); nautilus_directory_emit_files_changed (key, value); + g_list_free (value); } static void -hash_table_list_prepend (GHashTable *table, gconstpointer key, gpointer data) +call_get_file_info_free_list (gpointer key, gpointer value, gpointer user_data) { - GList *list; + g_assert (NAUTILUS_IS_DIRECTORY (key)); + g_assert (value != NULL); + g_assert (user_data == NULL); - list = g_hash_table_lookup (table, key); - list = g_list_prepend (list, data); - g_hash_table_insert (table, (gpointer) key, list); + nautilus_directory_get_info_for_new_files (key, value); + gnome_vfs_uri_list_free (value); +} + +void +nautilus_directory_notify_files_added (GList *uris) +{ + GHashTable *added_lists; + GList *p; + NautilusDirectory *directory; + const char *uri; + GnomeVFSURI *vfs_uri; + + /* Make a list of added files in each directory. */ + added_lists = g_hash_table_new (g_direct_hash, g_direct_equal); + + for (p = uris; p != NULL; p = p->next) { + uri = (const char *) p->data; + + /* See if the directory is already known. */ + directory = get_parent_directory_if_exists (uri); + if (directory == NULL) { + continue; + } + + /* If no one is monitoring files in the directory, nothing to do. */ + if (!nautilus_directory_is_file_list_monitored (directory)) { + continue; + } + + /* Collect the URIs to use. */ + vfs_uri = gnome_vfs_uri_new (uri); + if (vfs_uri == NULL) { + g_warning ("bad uri %s", uri); + continue; + } + hash_table_list_prepend (added_lists, directory, vfs_uri); + } + + + /* Now send out the changed signals. */ + g_hash_table_foreach (added_lists, call_get_file_info_free_list, NULL); + g_hash_table_destroy (added_lists); } void @@ -955,7 +968,7 @@ nautilus_directory_notify_files_removed (GList *uris) } /* Now send out the changed signals. */ - g_hash_table_foreach (changed_lists, call_files_changed, NULL); + g_hash_table_foreach (changed_lists, call_files_changed_free_list, NULL); g_hash_table_destroy (changed_lists); } @@ -970,7 +983,6 @@ nautilus_directory_notify_files_moved (GList *uri_pairs) GHashTable *added_lists, *changed_lists; GList **files; GnomeVFSFileInfo *info; - GnomeVFSResult result; /* Make a list of added and changed files in each directory. */ new_files_list = NULL; @@ -1016,28 +1028,23 @@ nautilus_directory_notify_files_moved (GList *uri_pairs) g_assert (g_list_find (*files, file) != NULL); *files = g_list_remove (*files, file); - /* FIXME bugzilla.eazel.com 465: - * Need to call get info in async mode. - */ + /* Make a copy and update the file name in the copy. */ info = gnome_vfs_file_info_new (); - result = gnome_vfs_get_file_info (pair->to_uri, info, - GNOME_VFS_FILE_INFO_DEFAULT, - NULL); - if (result == GNOME_VFS_OK) { - gnome_vfs_file_info_ref (info); - nautilus_file_update (file, info); - - /* Add to new directory. */ - files = &new_directory->details->files; - g_assert (g_list_find (*files, file) == NULL); - *files = g_list_prepend (*files, file); - - /* Handle notification in the new directory. */ - hash_table_list_prepend (added_lists, - new_directory, - file); - } + gnome_vfs_file_info_copy (info, file->details->info); + g_free (info->name); + info->name = uri_get_basename (pair->to_uri); + nautilus_file_update (file, info); gnome_vfs_file_info_unref (info); + + /* Add to new directory. */ + files = &new_directory->details->files; + g_assert (g_list_find (*files, file) == NULL); + *files = g_list_prepend (*files, file); + + /* Handle notification in the new directory. */ + hash_table_list_prepend (added_lists, + new_directory, + file); } /* If the old directory was monitoring files, then it @@ -1053,9 +1060,9 @@ nautilus_directory_notify_files_moved (GList *uri_pairs) } /* Now send out the changed and added signals for existing file objects. */ - g_hash_table_foreach (changed_lists, call_files_changed, NULL); + g_hash_table_foreach (changed_lists, call_files_changed_free_list, NULL); g_hash_table_destroy (changed_lists); - g_hash_table_foreach (added_lists, call_files_added, NULL); + g_hash_table_foreach (added_lists, call_files_added_free_list, NULL); g_hash_table_destroy (added_lists); /* Let the file objects go. */ diff --git a/libnautilus-private/nautilus-directory-async.c b/libnautilus-private/nautilus-directory-async.c index 15975ff61..cce2eff91 100644 --- a/libnautilus-private/nautilus-directory-async.c +++ b/libnautilus-private/nautilus-directory-async.c @@ -44,6 +44,7 @@ struct MetafileReadState { GnomeVFSAsyncHandle *handle; + gboolean is_open; gpointer buffer; size_t bytes_read; }; @@ -69,9 +70,6 @@ static void directory_load_done GnomeVFSResult result); static void directory_load_one (NautilusDirectory *directory, GnomeVFSFileInfo *info); -static void metafile_close_callback (GnomeVFSAsyncHandle *handle, - GnomeVFSResult result, - gpointer callback_data); static void metafile_read_callback (GnomeVFSAsyncHandle *handle, GnomeVFSResult result, gpointer buffer, @@ -100,6 +98,27 @@ static GnomeVFSDirectoryListPosition nautilus_gnome_vfs_directory_list_get_next_ GnomeVFSDirectoryListPosition position); static void process_pending_file_attribute_requests (NautilusDirectory *directory); +static void +empty_close_callback (GnomeVFSAsyncHandle *handle, + GnomeVFSResult result, + gpointer callback_data) +{ + /* Do nothing. */ +} + +static void +metafile_read_close (NautilusDirectory *directory) +{ + g_assert (directory->details->read_state->handle != NULL); + if (directory->details->read_state->is_open) { + gnome_vfs_async_close (directory->details->read_state->handle, + empty_close_callback, + directory); + directory->details->read_state->is_open = TRUE; + } + directory->details->read_state->handle = NULL; +} + static void metafile_read_done (NautilusDirectory *directory) { @@ -132,7 +151,9 @@ nautilus_metafile_read_cancel (NautilusDirectory *directory) return; } + g_assert (directory->details->read_state->handle != NULL); gnome_vfs_async_cancel (directory->details->read_state->handle); + metafile_read_close (directory); g_free (directory->details->read_state); directory->details->read_state = NULL; } @@ -194,14 +215,6 @@ metafile_read_complete (NautilusDirectory *directory) metafile_read_done (directory); } -static void -metafile_close_callback (GnomeVFSAsyncHandle *handle, - GnomeVFSResult result, - gpointer callback_data) -{ - /* Do nothing. */ -} - static void metafile_read_callback (GnomeVFSAsyncHandle *handle, GnomeVFSResult result, @@ -221,6 +234,7 @@ metafile_read_callback (GnomeVFSAsyncHandle *handle, if (result != GNOME_VFS_OK && result != GNOME_VFS_ERROR_EOF) { + metafile_read_close (directory); metafile_read_failed (directory, result); return; } @@ -236,10 +250,7 @@ metafile_read_callback (GnomeVFSAsyncHandle *handle, return; } - gnome_vfs_async_close (directory->details->read_state->handle, - metafile_close_callback, - directory); - + metafile_read_close (directory); metafile_read_complete (directory); } @@ -273,6 +284,7 @@ metafile_read_open_callback (GnomeVFSAsyncHandle *handle, return; } + directory->details->read_state->is_open = TRUE; metafile_read_some (directory); } @@ -356,15 +368,17 @@ metafile_write_callback (GnomeVFSAsyncHandle *handle, g_assert (directory->details->write_state->buffer == buffer); g_assert (directory->details->write_state->size == bytes_requested); + g_assert (directory->details->write_state->handle != NULL); + gnome_vfs_async_close (directory->details->write_state->handle, + empty_close_callback, + directory); + directory->details->write_state->handle = NULL; + if (result != GNOME_VFS_OK) { metafile_write_failed (directory, result); return; } - gnome_vfs_async_close (directory->details->write_state->handle, - metafile_close_callback, - directory); - metafile_write_complete (directory); } @@ -751,7 +765,7 @@ dequeue_pending_idle_callback (gpointer callback_data) /* If we stopped monitoring, then throw away these. */ if (!nautilus_directory_is_file_list_monitored (directory)) { - nautilus_gnome_vfs_file_info_list_free (pending_file_info); + gnome_vfs_file_info_list_free (pending_file_info); return FALSE; } @@ -775,7 +789,7 @@ dequeue_pending_idle_callback (gpointer callback_data) pending_files = g_list_prepend (pending_files, file); } } - nautilus_gnome_vfs_file_info_list_free (pending_file_info); + gnome_vfs_file_info_list_free (pending_file_info); /* Tell the objects that are monitoring about these new files. */ nautilus_directory_emit_files_added (directory, pending_files); @@ -801,8 +815,11 @@ nautilus_directory_schedule_dequeue_pending (NautilusDirectory *directory) static void directory_load_one (NautilusDirectory *directory, - GnomeVFSFileInfo *info) + GnomeVFSFileInfo *info) { + if (info == NULL) { + return; + } gnome_vfs_file_info_ref (info); directory->details->pending_file_info = g_list_prepend (directory->details->pending_file_info, info); @@ -838,10 +855,10 @@ nautilus_gnome_vfs_directory_list_get_next_position (GnomeVFSDirectoryList *list static void directory_load_callback (GnomeVFSAsyncHandle *handle, - GnomeVFSResult result, - GnomeVFSDirectoryList *list, - guint entries_read, - gpointer callback_data) + GnomeVFSResult result, + GnomeVFSDirectoryList *list, + guint entries_read, + gpointer callback_data) { NautilusDirectory *directory; GnomeVFSDirectoryListPosition last_handled, p; @@ -1149,15 +1166,46 @@ process_pending_file_attribute_requests (NautilusDirectory *directory) g_free (uri); } -void -nautilus_gnome_vfs_file_info_list_unref (GList *list) +static void +new_files_callback (GnomeVFSAsyncHandle *handle, + GList *results, + gpointer callback_data) { - g_list_foreach (list, (GFunc) gnome_vfs_file_info_unref, NULL); + GList **handles, *p; + NautilusDirectory *directory; + GnomeVFSGetFileInfoResult *result; + + directory = NAUTILUS_DIRECTORY (callback_data); + handles = &directory->details->get_file_infos_in_progress; + g_assert (handle == NULL || g_list_find (*handles, handle) != NULL); + + /* Note that this call is done. */ + *handles = g_list_remove (*handles, handle); + + /* Queue up the new files. */ + for (p = results; p != NULL; p = p->next) { + result = p->data; + directory_load_one (directory, result->file_info); + } } void -nautilus_gnome_vfs_file_info_list_free (GList *list) +nautilus_directory_get_info_for_new_files (NautilusDirectory *directory, + GList *vfs_uri_list) { - nautilus_gnome_vfs_file_info_list_unref (list); - g_list_free (list); + GnomeVFSAsyncHandle *handle; + + gnome_vfs_async_get_file_info + (&handle, + vfs_uri_list, + (GNOME_VFS_FILE_INFO_GETMIMETYPE + | GNOME_VFS_FILE_INFO_FASTMIMETYPE + | GNOME_VFS_FILE_INFO_FOLLOWLINKS), + NULL, + new_files_callback, + directory); + + directory->details->get_file_infos_in_progress + = g_list_prepend (directory->details->get_file_infos_in_progress, + handle); } diff --git a/libnautilus-private/nautilus-directory-private.h b/libnautilus-private/nautilus-directory-private.h index a81263a4f..e6f88f640 100644 --- a/libnautilus-private/nautilus-directory-private.h +++ b/libnautilus-private/nautilus-directory-private.h @@ -65,9 +65,12 @@ struct NautilusDirectoryDetails gboolean directory_loaded; GnomeVFSAsyncHandle *directory_load_in_progress; GnomeVFSDirectoryListPosition directory_load_list_last_handled; - GList *pending_file_info; + + GList *pending_file_info; /* list of GnomeVFSFileInfo */ guint dequeue_pending_idle_id; + GList *get_file_infos_in_progress; /* list of GnomeVFSAsyncHandle* */ + GnomeVFSAsyncHandle *count_in_progress; NautilusFile *count_file; }; @@ -112,6 +115,8 @@ void nautilus_directory_file_monitor_add_internal (NautilusDirectory void nautilus_directory_file_monitor_remove_internal (NautilusDirectory *directory, NautilusFile *file, gconstpointer client); +void nautilus_directory_get_info_for_new_files (NautilusDirectory *directory, + GList *vfs_uris); gboolean nautilus_directory_is_file_list_monitored (NautilusDirectory *directory); void nautilus_directory_remove_file_monitor_link (NautilusDirectory *directory, GList *link); @@ -149,5 +154,3 @@ int nautilus_directory_number_outstanding (void); /* Shared functions not directly related to NautilusDirectory/File. */ int nautilus_compare_file_with_name (gconstpointer a, gconstpointer b); -void nautilus_gnome_vfs_file_info_list_free (GList *list); -void nautilus_gnome_vfs_file_info_list_unref (GList *list); diff --git a/libnautilus-private/nautilus-directory.c b/libnautilus-private/nautilus-directory.c index 8fa42ffa8..e84880968 100644 --- a/libnautilus-private/nautilus-directory.c +++ b/libnautilus-private/nautilus-directory.c @@ -154,6 +154,7 @@ nautilus_directory_destroy (GtkObject *object) g_assert (directory->details->write_state == NULL); nautilus_metafile_read_cancel (directory); + g_assert (directory->details->read_state == NULL); if (nautilus_directory_is_file_list_monitored (directory)) { nautilus_directory_stop_monitoring_file_list (directory); @@ -185,7 +186,7 @@ nautilus_directory_destroy (GtkObject *object) g_assert (directory->details->directory_load_in_progress == NULL); g_assert (directory->details->count_in_progress == NULL); g_assert (directory->details->dequeue_pending_idle_id == 0); - nautilus_gnome_vfs_file_info_list_unref (directory->details->pending_file_info); + gnome_vfs_file_info_list_unref (directory->details->pending_file_info); g_assert (directory->details->write_metafile_idle_id == 0); g_free (directory->details); @@ -852,50 +853,18 @@ get_file_if_exists (const char *uri) return file; } -void -nautilus_directory_notify_files_added (GList *uris) +static void +hash_table_list_prepend (GHashTable *table, gconstpointer key, gpointer data) { - GList *p; - NautilusDirectory *directory; - GnomeVFSFileInfo *info; - const char *uri; - GnomeVFSResult result; - - /* FIXME bugzilla.eazel.com 465: - gnome_vfs_file_info calls need to be - called asynchronously. We probably need a new gnome_vfs call that - takes a list of URIs and generates a list of file info structures. - */ - for (p = uris; p != NULL; p = p->next) { - uri = (const char *) p->data; - - /* See if the directory is already known. */ - directory = get_parent_directory_if_exists (uri); - if (directory == NULL) { - continue; - } - - /* If no one is monitoring files in the directory, nothing to do. */ - if (!nautilus_directory_is_file_list_monitored (directory)) { - continue; - } + GList *list; - info = gnome_vfs_file_info_new (); - result = gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_DEFAULT, NULL); - if (result == GNOME_VFS_OK) { - gnome_vfs_file_info_ref (info); - directory->details->pending_file_info - = g_list_prepend (directory->details->pending_file_info, info); - - nautilus_directory_schedule_dequeue_pending (directory); - } - - gnome_vfs_file_info_unref (info); - } + list = g_hash_table_lookup (table, key); + list = g_list_prepend (list, data); + g_hash_table_insert (table, (gpointer) key, list); } static void -call_files_added (gpointer key, gpointer value, gpointer user_data) +call_files_added_free_list (gpointer key, gpointer value, gpointer user_data) { g_assert (NAUTILUS_IS_DIRECTORY (key)); g_assert (value != NULL); @@ -904,26 +873,70 @@ call_files_added (gpointer key, gpointer value, gpointer user_data) gtk_signal_emit (GTK_OBJECT (key), signals[FILES_ADDED], value); + g_list_free (value); } static void -call_files_changed (gpointer key, gpointer value, gpointer user_data) +call_files_changed_free_list (gpointer key, gpointer value, gpointer user_data) { g_assert (NAUTILUS_IS_DIRECTORY (key)); g_assert (value != NULL); g_assert (user_data == NULL); nautilus_directory_emit_files_changed (key, value); + g_list_free (value); } static void -hash_table_list_prepend (GHashTable *table, gconstpointer key, gpointer data) +call_get_file_info_free_list (gpointer key, gpointer value, gpointer user_data) { - GList *list; + g_assert (NAUTILUS_IS_DIRECTORY (key)); + g_assert (value != NULL); + g_assert (user_data == NULL); - list = g_hash_table_lookup (table, key); - list = g_list_prepend (list, data); - g_hash_table_insert (table, (gpointer) key, list); + nautilus_directory_get_info_for_new_files (key, value); + gnome_vfs_uri_list_free (value); +} + +void +nautilus_directory_notify_files_added (GList *uris) +{ + GHashTable *added_lists; + GList *p; + NautilusDirectory *directory; + const char *uri; + GnomeVFSURI *vfs_uri; + + /* Make a list of added files in each directory. */ + added_lists = g_hash_table_new (g_direct_hash, g_direct_equal); + + for (p = uris; p != NULL; p = p->next) { + uri = (const char *) p->data; + + /* See if the directory is already known. */ + directory = get_parent_directory_if_exists (uri); + if (directory == NULL) { + continue; + } + + /* If no one is monitoring files in the directory, nothing to do. */ + if (!nautilus_directory_is_file_list_monitored (directory)) { + continue; + } + + /* Collect the URIs to use. */ + vfs_uri = gnome_vfs_uri_new (uri); + if (vfs_uri == NULL) { + g_warning ("bad uri %s", uri); + continue; + } + hash_table_list_prepend (added_lists, directory, vfs_uri); + } + + + /* Now send out the changed signals. */ + g_hash_table_foreach (added_lists, call_get_file_info_free_list, NULL); + g_hash_table_destroy (added_lists); } void @@ -955,7 +968,7 @@ nautilus_directory_notify_files_removed (GList *uris) } /* Now send out the changed signals. */ - g_hash_table_foreach (changed_lists, call_files_changed, NULL); + g_hash_table_foreach (changed_lists, call_files_changed_free_list, NULL); g_hash_table_destroy (changed_lists); } @@ -970,7 +983,6 @@ nautilus_directory_notify_files_moved (GList *uri_pairs) GHashTable *added_lists, *changed_lists; GList **files; GnomeVFSFileInfo *info; - GnomeVFSResult result; /* Make a list of added and changed files in each directory. */ new_files_list = NULL; @@ -1016,28 +1028,23 @@ nautilus_directory_notify_files_moved (GList *uri_pairs) g_assert (g_list_find (*files, file) != NULL); *files = g_list_remove (*files, file); - /* FIXME bugzilla.eazel.com 465: - * Need to call get info in async mode. - */ + /* Make a copy and update the file name in the copy. */ info = gnome_vfs_file_info_new (); - result = gnome_vfs_get_file_info (pair->to_uri, info, - GNOME_VFS_FILE_INFO_DEFAULT, - NULL); - if (result == GNOME_VFS_OK) { - gnome_vfs_file_info_ref (info); - nautilus_file_update (file, info); - - /* Add to new directory. */ - files = &new_directory->details->files; - g_assert (g_list_find (*files, file) == NULL); - *files = g_list_prepend (*files, file); - - /* Handle notification in the new directory. */ - hash_table_list_prepend (added_lists, - new_directory, - file); - } + gnome_vfs_file_info_copy (info, file->details->info); + g_free (info->name); + info->name = uri_get_basename (pair->to_uri); + nautilus_file_update (file, info); gnome_vfs_file_info_unref (info); + + /* Add to new directory. */ + files = &new_directory->details->files; + g_assert (g_list_find (*files, file) == NULL); + *files = g_list_prepend (*files, file); + + /* Handle notification in the new directory. */ + hash_table_list_prepend (added_lists, + new_directory, + file); } /* If the old directory was monitoring files, then it @@ -1053,9 +1060,9 @@ nautilus_directory_notify_files_moved (GList *uri_pairs) } /* Now send out the changed and added signals for existing file objects. */ - g_hash_table_foreach (changed_lists, call_files_changed, NULL); + g_hash_table_foreach (changed_lists, call_files_changed_free_list, NULL); g_hash_table_destroy (changed_lists); - g_hash_table_foreach (added_lists, call_files_added, NULL); + g_hash_table_foreach (added_lists, call_files_added_free_list, NULL); g_hash_table_destroy (added_lists); /* Let the file objects go. */ -- cgit v1.2.1