diff options
author | Alexander Larsson <alexl@redhat.com> | 2005-12-01 13:27:19 +0000 |
---|---|---|
committer | Alexander Larsson <alexl@src.gnome.org> | 2005-12-01 13:27:19 +0000 |
commit | 76bb34583a5ecd192c736b93a1b3dd9fed526302 (patch) | |
tree | 5aa4cb937ffbab4674fbb3720712d7aa23360c72 /src/file-manager | |
parent | e11a936656f6f23847dddaad47120b51c3c85fd9 (diff) | |
download | nautilus-76bb34583a5ecd192c736b93a1b3dd9fed526302.tar.gz |
Check for update-mime-database
2005-12-01 Alexander Larsson <alexl@redhat.com>
* configure.in:
Check for update-mime-database
* data/.cvsignore:
* data/Makefile.am:
* data/nautilus.xml.in:
Add mime database entries for saved searches.
* libnautilus-private/Makefile.am:
* libnautilus-private/nautilus-saved-search-file.[ch]:
Special file type for saved search files to pretend that
they are directories.
* libnautilus-private/nautilus-directory.[ch]:
Make nautilus_directory_ref return its arg.
Create NautilusSearchDirectory for saved searches.
* libnautilus-private/nautilus-file-dnd.c:
Non-editable directories do not accept drops.
* libnautilus-private/nautilus-file-private.h:
* libnautilus-private/nautilus-file.h:
Move nautilus_file_get_existing to public header.
* libnautilus-private/nautilus-file.c:
Create saved search files at right time
* libnautilus-private/nautilus-marshal.list:
Add new marshallers
* libnautilus-private/nautilus-monitor.c:
Remove some spew
* libnautilus-private/nautilus-search-directory.[ch]:
Split out search file loading to a separate function.
* libnautilus-private/nautilus-tree-view-drag-dest.c:
Handle several layers of cannot accept drop.
* src/file-manager/fm-directory-view.[ch]:
Make files be related to the directory they are in, since
a file can be in a tree multiple times, with searches.
Sorting us now done in base class, and inheriting classes just
add a compare function.
Fix file leak in new_folder_done.
* src/file-manager/fm-icon-view.c:
Update to new base class API.
In scroll_to_file, don't create a NautilusFile if it doesn't exist.
* src/file-manager/fm-list-model.[ch]:
Rearrange data so that we can have one file in multiple dirs.
Still problems with the same directory in multiple dirs.
In scroll_to_file, don't create a NautilusFile if it doesn't exist.
Fix leak in each_path_get_data_binder
* src/file-manager/fm-list-view.c:
Update to new APIs (base class and model).
Fix leak in fm_list_view_get_selection_foreach_func.
--- nautilus-search2 branch ---
Diffstat (limited to 'src/file-manager')
-rw-r--r-- | src/file-manager/fm-directory-view.c | 284 | ||||
-rw-r--r-- | src/file-manager/fm-directory-view.h | 17 | ||||
-rw-r--r-- | src/file-manager/fm-icon-view.c | 58 | ||||
-rw-r--r-- | src/file-manager/fm-list-model.c | 381 | ||||
-rw-r--r-- | src/file-manager/fm-list-model.h | 22 | ||||
-rw-r--r-- | src/file-manager/fm-list-view.c | 106 |
6 files changed, 527 insertions, 341 deletions
diff --git a/src/file-manager/fm-directory-view.c b/src/file-manager/fm-directory-view.c index 440847ffc..72db189a1 100644 --- a/src/file-manager/fm-directory-view.c +++ b/src/file-manager/fm-directory-view.c @@ -280,6 +280,11 @@ typedef struct { gboolean cancelled; } ActivateParameters; +typedef struct { + NautilusFile *file; + NautilusDirectory *directory; +} FileAndDirectory; + enum { GNOME_COPIED_FILES, UTF8_STRING @@ -432,6 +437,79 @@ typedef struct { } CreateTemplateParameters; + +static GList * +file_and_directory_list_to_files (GList *fad_list) +{ + GList *res, *l; + FileAndDirectory *fad; + + res = NULL; + for (l = fad_list; l != NULL; l = l->next) { + fad = l->data; + res = g_list_prepend (res, nautilus_file_ref (fad->file)); + } + return g_list_reverse (res); +} + + +static GList * +file_and_directory_list_from_files (NautilusDirectory *directory, GList *files) +{ + GList *res, *l; + FileAndDirectory *fad; + + res = NULL; + for (l = files; l != NULL; l = l->next) { + fad = g_new0 (FileAndDirectory, 1); + fad->directory = nautilus_directory_ref (directory); + fad->file = nautilus_file_ref (l->data); + res = g_list_prepend (res, fad); + } + return g_list_reverse (res); +} + +static void +file_and_directory_free (FileAndDirectory *fad) +{ + nautilus_directory_unref (fad->directory); + nautilus_file_unref (fad->file); + g_free (fad); +} + + +static void +file_and_directory_list_free (GList *list) +{ + GList *l; + + for (l = list; l != NULL; l = l->next) { + file_and_directory_free (l->data); + } +} + +static gboolean +file_and_directory_equal (gconstpointer v1, + gconstpointer v2) +{ + const FileAndDirectory *fad1, *fad2; + fad1 = v1; + fad2 = v2; + + return (fad1->file == fad2->file && + fad1->directory == fad2->directory); +} + +static guint +file_and_directory_hash (gconstpointer v) +{ + const FileAndDirectory *fad; + + fad = v; + return GPOINTER_TO_UINT (fad->file) ^ GPOINTER_TO_UINT (fad->directory); +} + + static ApplicationLaunchParameters * application_launch_parameters_new (GnomeVFSMimeApplication *application, NautilusFile *file, @@ -1626,7 +1704,11 @@ fm_directory_view_init (FMDirectoryView *view) view->details = g_new0 (FMDirectoryViewDetails, 1); - view->details->non_ready_files = g_hash_table_new (NULL, NULL); + view->details->non_ready_files = + g_hash_table_new_full (file_and_directory_hash, + file_and_directory_equal, + (GDestroyNotify)file_and_directory_free, + NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (view), GTK_POLICY_AUTOMATIC, @@ -2127,6 +2209,7 @@ debuting_uri_data_free (DebutingUriData *data) static void debuting_uri_add_file_callback (FMDirectoryView *view, NautilusFile *new_file, + NautilusDirectory *directory, DebutingUriData *data) { char *uri; @@ -2134,7 +2217,7 @@ debuting_uri_add_file_callback (FMDirectoryView *view, uri = nautilus_file_get_uri (new_file); if (g_hash_table_remove (data->debuting_uris, uri)) { - g_object_ref (new_file); + nautilus_file_ref (new_file); data->added_files = g_list_prepend (data->added_files, new_file); if (g_hash_table_size (data->debuting_uris) == 0) { @@ -2165,7 +2248,7 @@ copy_move_done_data_free (CopyMoveDoneData *data) } static void -pre_copy_move_add_file_callback (FMDirectoryView *view, NautilusFile *new_file, CopyMoveDoneData *data) +pre_copy_move_add_file_callback (FMDirectoryView *view, NautilusFile *new_file, NautilusDirectory *directory, CopyMoveDoneData *data) { g_object_ref (new_file); data->added_files = g_list_prepend (data->added_files, new_file); @@ -2301,29 +2384,21 @@ copy_move_done_callback (GHashTable *debuting_uris, gpointer data) } static gboolean -real_file_still_belongs (FMDirectoryView *view, NautilusFile *file) +real_file_still_belongs (FMDirectoryView *view, NautilusFile *file, NautilusDirectory *directory) { - GList *node; - - if (nautilus_directory_contains_file (view->details->model, file)) { - return TRUE; - } - - for (node = view->details->subdirectory_list; node != NULL; node = node->next) { - if (nautilus_directory_contains_file (NAUTILUS_DIRECTORY (node->data), - file)) { - return TRUE; - } + if (view->details->model != directory && + g_list_find (view->details->subdirectory_list, directory) == NULL) { + return FALSE; } - return FALSE; + return nautilus_directory_contains_file (directory, file); } static gboolean -still_should_show_file (FMDirectoryView *view, NautilusFile *file) +still_should_show_file (FMDirectoryView *view, NautilusFile *file, NautilusDirectory *directory) { return fm_directory_view_should_show_file (view, file) - && EEL_INVOKE_METHOD (FM_DIRECTORY_VIEW_CLASS, view, file_still_belongs, (view, file)); + && EEL_INVOKE_METHOD (FM_DIRECTORY_VIEW_CLASS, view, file_still_belongs, (view, file, directory)); } static gboolean @@ -2332,6 +2407,31 @@ ready_to_load (NautilusFile *file) return nautilus_icon_factory_is_icon_ready_for_file (file); } +static int +compare_files_cover (gconstpointer a, gconstpointer b, gpointer callback_data) +{ + const FileAndDirectory *fad1, *fad2; + FMDirectoryView *view; + + view = callback_data; + fad1 = a; fad2 = b; + + if (fad1->directory < fad2->directory) { + return -1; + } else if (fad1->directory > fad2->directory) { + return 1; + } else { + return EEL_INVOKE_METHOD (FM_DIRECTORY_VIEW_CLASS, view, compare_files, + (view, fad1->file, fad2->file)); + } +} +static void +sort_files (FMDirectoryView *view, GList **list) +{ + *list = g_list_sort_with_data (*list, compare_files_cover, view); + +} + /* Go through all the new added and changed files. * Put any that are not ready to load in the non_ready_files hash table. * Add all the rest to the old_added_files and old_changed_files lists. @@ -2342,8 +2442,8 @@ process_new_files (FMDirectoryView *view) { GList *new_added_files, *new_changed_files, *old_added_files, *old_changed_files; GHashTable *non_ready_files; - GList *node; - NautilusFile *file; + GList *node, *next; + FileAndDirectory *pending; gboolean in_non_ready; new_added_files = view->details->new_added_files; @@ -2359,56 +2459,54 @@ process_new_files (FMDirectoryView *view) /* Newly added files go into the old_added_files list if they're * ready, and into the hash table if they're not. */ - for (node = new_added_files; node != NULL; node = node->next) { - file = NAUTILUS_FILE (node->data); - in_non_ready = g_hash_table_lookup (non_ready_files, file) != NULL; - if (fm_directory_view_should_show_file (view, file)) { - if (ready_to_load (file)) { + for (node = new_added_files; node != NULL; node = next) { + next = node->next; + pending = (FileAndDirectory *)node->data; + in_non_ready = g_hash_table_lookup (non_ready_files, pending) != NULL; + if (fm_directory_view_should_show_file (view, pending->file)) { + if (ready_to_load (pending->file)) { if (in_non_ready) { - g_hash_table_remove (non_ready_files, file); - nautilus_file_unref (file); + g_hash_table_remove (non_ready_files, pending); } - nautilus_file_ref (file); - old_added_files = g_list_prepend (old_added_files, file); + new_added_files = g_list_delete_link (new_added_files, node); + old_added_files = g_list_prepend (old_added_files, pending); } else { if (!in_non_ready) { - nautilus_file_ref (file); - g_hash_table_insert (non_ready_files, file, file); + new_added_files = g_list_delete_link (new_added_files, node); + g_hash_table_insert (non_ready_files, pending, pending); } } } } - nautilus_file_list_free (new_added_files); + file_and_directory_list_free (new_added_files); /* Newly changed files go into the old_added_files list if they're ready * and were seen non-ready in the past, into the old_changed_files list * if they are read and were not seen non-ready in the past, and into * the hash table if they're not ready. */ - for (node = new_changed_files; node != NULL; node = node->next) { - file = NAUTILUS_FILE (node->data); - if (!still_should_show_file (view, file) || ready_to_load (file)) { - if (g_hash_table_lookup (non_ready_files, file) != NULL) { - g_hash_table_remove (non_ready_files, file); - nautilus_file_unref (file); - if (still_should_show_file (view, file)) { - nautilus_file_ref (file); - old_added_files = g_list_prepend (old_added_files, file); + for (node = new_changed_files; node != NULL; node = next) { + next = node->next; + pending = (FileAndDirectory *)node->data; + if (!still_should_show_file (view, pending->file, pending->directory) || ready_to_load (pending->file)) { + if (g_hash_table_lookup (non_ready_files, pending) != NULL) { + g_hash_table_remove (non_ready_files, pending); + if (still_should_show_file (view, pending->file, pending->directory)) { + new_changed_files = g_list_delete_link (new_changed_files, node); + old_added_files = g_list_prepend (old_added_files, pending); } - } else if (fm_directory_view_should_show_file(view, file)) { - nautilus_file_ref (file); - old_changed_files = g_list_prepend - (old_changed_files, file); + } else if (fm_directory_view_should_show_file (view, pending->file)) { + new_changed_files = g_list_delete_link (new_changed_files, node); + old_changed_files = g_list_prepend (old_changed_files, pending); } } } - nautilus_file_list_free (new_changed_files); + file_and_directory_list_free (new_changed_files); /* If any files were added to old_added_files, then resort it. */ if (old_added_files != view->details->old_added_files) { view->details->old_added_files = old_added_files; - EEL_INVOKE_METHOD (FM_DIRECTORY_VIEW_CLASS, view, sort_files, - (view, &view->details->old_added_files)); + sort_files (view, &view->details->old_added_files); } /* Resort old_changed_files too, since file attributes @@ -2416,8 +2514,7 @@ process_new_files (FMDirectoryView *view) */ if (old_changed_files != view->details->old_changed_files) { view->details->old_changed_files = old_changed_files; - EEL_INVOKE_METHOD (FM_DIRECTORY_VIEW_CLASS, view, sort_files, - (view, &view->details->old_changed_files)); + sort_files (view, &view->details->old_changed_files); } } @@ -2426,8 +2523,8 @@ static void process_old_files (FMDirectoryView *view) { GList *files_added, *files_changed, *node; - NautilusFile *file; - GList *selection; + FileAndDirectory *pending; + GList *selection, *files; gboolean send_selection_change; files_added = view->details->old_added_files; @@ -2439,37 +2536,34 @@ process_old_files (FMDirectoryView *view) g_signal_emit (view, signals[BEGIN_FILE_CHANGES], 0); for (node = files_added; node != NULL; node = node->next) { - file = NAUTILUS_FILE (node->data); + pending = node->data; g_signal_emit (view, - signals[ADD_FILE], 0, file); + signals[ADD_FILE], 0, pending->file, pending->directory); } for (node = files_changed; node != NULL; node = node->next) { - file = NAUTILUS_FILE (node->data); - + pending = node->data; g_signal_emit (view, - signals[still_should_show_file (view, file) + signals[still_should_show_file (view, pending->file, pending->directory) ? FILE_CHANGED : REMOVE_FILE], 0, - file); + pending->file, pending->directory); } g_signal_emit (view, signals[END_FILE_CHANGES], 0); if (files_changed != NULL) { selection = fm_directory_view_get_selection (view); + files = file_and_directory_list_to_files (files_changed); send_selection_change = eel_g_lists_sort_and_check_for_intersection - (&files_changed, &selection); + (&files, &selection); + nautilus_file_list_free (files); nautilus_file_list_free (selection); } - - nautilus_file_list_free (view->details->old_added_files); + + file_and_directory_list_free (view->details->old_added_files); view->details->old_added_files = NULL; - /* We free files_changed here instead of view->details->old_changed_files - * because the call to eel_g_lists_sort_and_check_for_intersection might - * change the first element, and so we might lose files to free. - */ - nautilus_file_list_free (files_changed); + file_and_directory_list_free (view->details->old_changed_files); view->details->old_changed_files = NULL; } @@ -2646,6 +2740,7 @@ unschedule_display_of_pending_files (FMDirectoryView *view) static void queue_pending_files (FMDirectoryView *view, + NautilusDirectory *directory, GList *files, GList **pending_list) { @@ -2669,10 +2764,12 @@ queue_pending_files (FMDirectoryView *view, } } - *pending_list = g_list_concat (nautilus_file_list_copy (files), + + + *pending_list = g_list_concat (file_and_directory_list_from_files (directory, files), *pending_list); - if (! view->details->loading || nautilus_directory_are_all_files_seen (view->details->model)) { + if (! view->details->loading || nautilus_directory_are_all_files_seen (directory)) { schedule_idle_display_of_pending_files (view); } } @@ -2685,7 +2782,7 @@ files_added_callback (NautilusDirectory *directory, FMDirectoryView *view; view = FM_DIRECTORY_VIEW (callback_data); - queue_pending_files (view, files, &view->details->new_added_files); + queue_pending_files (view, directory, files, &view->details->new_added_files); /* The number of items could have changed */ schedule_update_status (view); @@ -2697,9 +2794,9 @@ files_changed_callback (NautilusDirectory *directory, gpointer callback_data) { FMDirectoryView *view; - + view = FM_DIRECTORY_VIEW (callback_data); - queue_pending_files (view, files, &view->details->new_changed_files); + queue_pending_files (view, directory, files, &view->details->new_changed_files); /* The free space or the number of items could have changed */ schedule_update_status (view); @@ -2766,24 +2863,6 @@ real_load_error (FMDirectoryView *view, GnomeVFSResult result, const char *error view->details->reported_load_error = TRUE; } -/** - * fm_directory_queue_notice_file_change - * - * Called by a subclass to put a file into the queue of files to update. - * This is only necessary when the subclass is monitoring files other than - * the ones in the directory for this location. - */ -void -fm_directory_view_queue_file_change (FMDirectoryView *view, NautilusFile *file) -{ - GList singleton_list; - - singleton_list.data = file; - singleton_list.next = NULL; - singleton_list.prev = NULL; - queue_pending_files (view, &singleton_list, &view->details->new_changed_files); -} - void fm_directory_view_add_subdirectory (FMDirectoryView *view, NautilusDirectory*directory) @@ -2800,7 +2879,7 @@ fm_directory_view_add_subdirectory (FMDirectoryView *view, NAUTILUS_FILE_ATTRIBUTE_MIME_TYPE | NAUTILUS_FILE_ATTRIBUTE_DISPLAY_NAME | NAUTILUS_FILE_ATTRIBUTE_EXTENSION_INFO; - + nautilus_directory_file_monitor_add (directory, &view->details->model, view->details->show_hidden_files, @@ -2821,7 +2900,7 @@ fm_directory_view_add_subdirectory (FMDirectoryView *view, void fm_directory_view_remove_subdirectory (FMDirectoryView *view, - NautilusDirectory*directory) + NautilusDirectory*directory) { g_assert (g_list_find (view->details->subdirectory_list, directory)); @@ -3625,7 +3704,8 @@ typedef struct { static void -track_newly_added_uris (FMDirectoryView *view, NautilusFile *new_file, gpointer user_data) +track_newly_added_uris (FMDirectoryView *view, NautilusFile *new_file, + NautilusDirectory *directory, gpointer user_data) { NewFolderData *data; @@ -3644,7 +3724,7 @@ new_folder_done (const char *new_folder_uri, gpointer user_data) NewFolderData *data; data = (NewFolderData *)user_data; - + directory_view = data->directory_view; if (directory_view == NULL) { @@ -3684,6 +3764,7 @@ new_folder_done (const char *new_folder_uri, gpointer user_data) (GClosureNotify)g_free, G_CONNECT_AFTER); } + nautilus_file_unref (file); fail: g_hash_table_destroy (data->added_uris); @@ -8696,10 +8777,6 @@ fm_directory_view_handle_text_drop (FMDirectoryView *view, } -static void -real_sort_files (FMDirectoryView *view, GList **files) -{ -} static GArray * real_get_selected_icon_locations (FMDirectoryView *view) @@ -8791,8 +8868,8 @@ fm_directory_view_class_init (FMDirectoryViewClass *klass) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (FMDirectoryViewClass, add_file), NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, NAUTILUS_TYPE_FILE); + nautilus_marshal_VOID__OBJECT_OBJECT, + G_TYPE_NONE, 2, NAUTILUS_TYPE_FILE, NAUTILUS_TYPE_DIRECTORY); signals[BEGIN_FILE_CHANGES] = g_signal_new ("begin_file_changes", G_TYPE_FROM_CLASS (klass), @@ -8847,8 +8924,8 @@ fm_directory_view_class_init (FMDirectoryViewClass *klass) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (FMDirectoryViewClass, file_changed), NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, NAUTILUS_TYPE_FILE); + nautilus_marshal_VOID__OBJECT_OBJECT, + G_TYPE_NONE, 2, NAUTILUS_TYPE_FILE, NAUTILUS_TYPE_DIRECTORY); signals[LOAD_ERROR] = g_signal_new ("load_error", G_TYPE_FROM_CLASS (klass), @@ -8863,8 +8940,8 @@ fm_directory_view_class_init (FMDirectoryViewClass *klass) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (FMDirectoryViewClass, remove_file), NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, NAUTILUS_TYPE_FILE); + nautilus_marshal_VOID__OBJECT_OBJECT, + G_TYPE_NONE, 2, NAUTILUS_TYPE_FILE, NAUTILUS_TYPE_DIRECTORY); klass->accepts_dragged_files = real_accepts_dragged_files; klass->file_limit_reached = real_file_limit_reached; @@ -8873,7 +8950,6 @@ fm_directory_view_class_init (FMDirectoryViewClass *klass) klass->get_selected_icon_locations = real_get_selected_icon_locations; klass->is_read_only = real_is_read_only; klass->load_error = real_load_error; - klass->sort_files = real_sort_files; klass->can_rename_file = can_rename_file; klass->start_renaming_file = start_renaming_file; klass->supports_creating_files = real_supports_creating_files; diff --git a/src/file-manager/fm-directory-view.h b/src/file-manager/fm-directory-view.h index 5ba694286..608ce16c1 100644 --- a/src/file-manager/fm-directory-view.h +++ b/src/file-manager/fm-directory-view.h @@ -76,16 +76,19 @@ struct FMDirectoryViewClass { * It must be replaced by each subclass. */ void (* add_file) (FMDirectoryView *view, - NautilusFile *file); + NautilusFile *file, + NautilusDirectory *directory); void (* remove_file) (FMDirectoryView *view, - NautilusFile *file); + NautilusFile *file, + NautilusDirectory *directory); /* The 'file_changed' signal is emitted to signal a change in a file, * including the file being removed. * It must be replaced by each subclass. */ void (* file_changed) (FMDirectoryView *view, - NautilusFile *file); + NautilusFile *file, + NautilusDirectory *directory); /* The 'end_file_changes' signal is emitted after a set of files * are added to the view. It can be replaced by a subclass to do any @@ -214,8 +217,9 @@ struct FMDirectoryViewClass { * to provide a sorting order to determine which files should be * presented when only a partial list is provided. */ - void (* sort_files) (FMDirectoryView *view, - GList **files); + int (* compare_files) (FMDirectoryView *view, + NautilusFile *a, + NautilusFile *b); /* get_emblem_names_to_exclude is a function pointer that subclasses * may override to specify a set of emblem names that should not @@ -284,7 +288,8 @@ struct FMDirectoryViewClass { gboolean select_all); gboolean (* file_still_belongs) (FMDirectoryView *view, - NautilusFile *file); + NautilusFile *file, + NautilusDirectory *directory); /* Preference change callbacks, overriden by icon and list views. * Icon and list views respond by synchronizing to the new preference diff --git a/src/file-manager/fm-icon-view.c b/src/file-manager/fm-icon-view.c index 1fc1e3aa7..c32ef6593 100644 --- a/src/file-manager/fm-icon-view.c +++ b/src/file-manager/fm-icon-view.c @@ -508,8 +508,10 @@ should_show_file_on_screen (FMDirectoryView *view, NautilusFile *file) } static void -fm_icon_view_remove_file (FMDirectoryView *view, NautilusFile *file) +fm_icon_view_remove_file (FMDirectoryView *view, NautilusFile *file, NautilusDirectory *directory) { + g_assert (directory == fm_directory_view_get_model (view)); + if (nautilus_icon_container_remove (get_icon_container (FM_ICON_VIEW (view)), NAUTILUS_ICON_CONTAINER_ICON_DATA (file))) { nautilus_file_unref (file); @@ -517,10 +519,12 @@ fm_icon_view_remove_file (FMDirectoryView *view, NautilusFile *file) } static void -fm_icon_view_add_file (FMDirectoryView *view, NautilusFile *file) +fm_icon_view_add_file (FMDirectoryView *view, NautilusFile *file, NautilusDirectory *directory) { FMIconView *icon_view; NautilusIconContainer *icon_container; + + g_assert (directory == fm_directory_view_get_model (view)); icon_view = FM_ICON_VIEW (view); icon_container = get_icon_container (icon_view); @@ -549,10 +553,12 @@ fm_icon_view_flush_added_files (FMDirectoryView *view) } static void -fm_icon_view_file_changed (FMDirectoryView *view, NautilusFile *file) +fm_icon_view_file_changed (FMDirectoryView *view, NautilusFile *file, NautilusDirectory *directory) { FMIconView *icon_view; + g_assert (directory == fm_directory_view_get_model (view)); + g_return_if_fail (view != NULL); icon_view = FM_ICON_VIEW (view); @@ -564,7 +570,7 @@ fm_icon_view_file_changed (FMDirectoryView *view, NautilusFile *file) } if (!should_show_file_on_screen (view, file)) { - fm_icon_view_remove_file (view, file); + fm_icon_view_remove_file (view, file, directory); } else { nautilus_icon_container_request_update @@ -2004,6 +2010,15 @@ fm_icon_view_compare_files (FMIconView *icon_view, icon_view->details->sort_reversed); } +static int +compare_files (FMDirectoryView *icon_view, + NautilusFile *a, + NautilusFile *b) +{ + return fm_icon_view_compare_files ((FMIconView *)icon_view, a, b); +} + + void fm_icon_view_filter_by_screen (FMIconView *icon_view, gboolean filter) @@ -2019,6 +2034,7 @@ fm_icon_view_screen_changed (GtkWidget *widget, FMDirectoryView *view; GList *files, *l; NautilusFile *file; + NautilusDirectory *directory; NautilusIconContainer *icon_container; if (GTK_WIDGET_CLASS (fm_icon_view_parent_class)->screen_changed) { @@ -2028,14 +2044,15 @@ fm_icon_view_screen_changed (GtkWidget *widget, view = FM_DIRECTORY_VIEW (widget); if (FM_ICON_VIEW (view)->details->filter_by_screen) { icon_container = get_icon_container (FM_ICON_VIEW (view)); - - files = nautilus_directory_get_file_list (fm_directory_view_get_model (view)); + + directory = fm_directory_view_get_model (view); + files = nautilus_directory_get_file_list (directory); for (l = files; l != NULL; l = l->next) { file = l->data; if (!should_show_file_on_screen (view, file)) { - fm_icon_view_remove_file (view, file); + fm_icon_view_remove_file (view, file, directory); } else { if (nautilus_icon_container_add (icon_container, NAUTILUS_ICON_CONTAINER_ICON_DATA (file), @@ -2050,27 +2067,6 @@ fm_icon_view_screen_changed (GtkWidget *widget, } } - -static int -compare_files_cover (gconstpointer a, gconstpointer b, gpointer callback_data) -{ - return fm_icon_view_compare_files (callback_data, - NAUTILUS_FILE (a), - NAUTILUS_FILE (b)); -} - -static void -fm_icon_view_sort_files (FMDirectoryView *view, GList **files) -{ - FMIconView *icon_view; - - icon_view = FM_ICON_VIEW (view); - if (!fm_icon_view_using_auto_layout (icon_view)) { - return; - } - *files = g_list_sort_with_data (*files, compare_files_cover, icon_view); -} - static void selection_changed_callback (NautilusIconContainer *container, FMIconView *icon_view) @@ -2568,7 +2564,9 @@ icon_view_scroll_to_file (NautilusView *view, icon_view = FM_ICON_VIEW (view); if (uri != NULL) { - file = nautilus_file_get (uri); + /* Only if existing, since we don't want to add the file to + the directory if it has been removed since then */ + file = nautilus_file_get_existing (uri); if (file != NULL) { nautilus_icon_container_scroll_to_icon (get_icon_container (icon_view), NAUTILUS_ICON_CONTAINER_ICON_DATA (file)); @@ -2613,7 +2611,7 @@ fm_icon_view_class_init (FMIconViewClass *klass) fm_directory_view_class->reveal_selection = fm_icon_view_reveal_selection; fm_directory_view_class->select_all = fm_icon_view_select_all; fm_directory_view_class->set_selection = fm_icon_view_set_selection; - fm_directory_view_class->sort_files = fm_icon_view_sort_files; + fm_directory_view_class->compare_files = compare_files; fm_directory_view_class->zoom_to_level = fm_icon_view_zoom_to_level; fm_directory_view_class->get_zoom_level = fm_icon_view_get_zoom_level; fm_directory_view_class->click_policy_changed = fm_icon_view_click_policy_changed; diff --git a/src/file-manager/fm-list-model.c b/src/file-manager/fm-list-model.c index e1f4a5e7c..eb1017213 100644 --- a/src/file-manager/fm-list-model.c +++ b/src/file-manager/fm-list-model.c @@ -52,15 +52,12 @@ static int fm_list_model_file_entry_compare_func (gconstpointer a, gconstpointer b, gpointer user_data); -static int fm_list_model_compare_func (gconstpointer a, - gconstpointer b, - gpointer user_data); - static GObjectClass *parent_class; struct FMListModelDetails { GSequence *files; - GHashTable *reverse_map; /* map from files to GSequencePtr's */ + GHashTable *directory_reverse_map; /* map from directory to GSequencePtr's */ + GHashTable *top_reverse_map; /* map from files in top dir to GSequencePtr's */ int stamp; @@ -86,6 +83,7 @@ typedef struct FileEntry FileEntry; struct FileEntry { NautilusFile *file; + GHashTable *reverse_map; /* map from files to GSequencePtr's */ NautilusDirectory *subdirectory; FileEntry *parent; GSequence *files; @@ -105,6 +103,10 @@ static void file_entry_free (FileEntry *file_entry) { nautilus_file_unref (file_entry->file); + if (file_entry->reverse_map) { + g_hash_table_destroy (file_entry->reverse_map); + file_entry->reverse_map = NULL; + } if (file_entry->subdirectory != NULL) { nautilus_directory_unref (file_entry->subdirectory); } @@ -160,6 +162,16 @@ fm_list_model_get_column_type (GtkTreeModel *tree_model, int index) } } +static void +fm_list_model_ptr_to_iter (FMListModel *model, GSequencePtr ptr, GtkTreeIter *iter) +{ + g_assert (!g_sequence_ptr_is_end (ptr)); + if (iter != NULL) { + iter->stamp = model->details->stamp; + iter->user_data = ptr; + } +} + static gboolean fm_list_model_get_iter (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreePath *path) { @@ -185,10 +197,7 @@ fm_list_model_get_iter (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreePath files = file_entry->files; } - iter->stamp = model->details->stamp; - iter->user_data = ptr; - - g_assert (!g_sequence_ptr_is_end (iter->user_data)); + fm_list_model_ptr_to_iter (model, ptr, iter); return TRUE; } @@ -494,24 +503,118 @@ fm_list_model_iter_parent (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeI return TRUE; } -gboolean -fm_list_model_get_tree_iter_from_file (FMListModel *model, NautilusFile *file, GtkTreeIter *iter) +static GSequencePtr +lookup_file (FMListModel *model, NautilusFile *file, + NautilusDirectory *directory) +{ + FileEntry *file_entry; + GSequencePtr ptr, parent_ptr; + + parent_ptr = NULL; + if (directory) { + parent_ptr = g_hash_table_lookup (model->details->directory_reverse_map, + directory); + } + + if (parent_ptr) { + file_entry = g_sequence_ptr_get_data (parent_ptr); + ptr = g_hash_table_lookup (file_entry->reverse_map, file); + } else { + ptr = g_hash_table_lookup (model->details->top_reverse_map, file); + } + + if (ptr) { + g_assert (((FileEntry *)g_sequence_ptr_get_data (ptr))->file == file); + } + + return ptr; +} + + +struct GetIters { + FMListModel *model; + NautilusFile *file; + GList *iters; +}; + +static void +dir_to_iters (struct GetIters *data, + GHashTable *reverse_map) { GSequencePtr ptr; + + ptr = g_hash_table_lookup (reverse_map, data->file); + if (ptr) { + GtkTreeIter *iter; + iter = g_new0 (GtkTreeIter, 1); + fm_list_model_ptr_to_iter (data->model, ptr, iter); + data->iters = g_list_prepend (data->iters, iter); + } +} + +static void +file_to_iter_cb (gpointer key, + gpointer value, + gpointer user_data) +{ + struct GetIters *data; + FileEntry *dir_file_entry; + + data = user_data; + dir_file_entry = g_sequence_ptr_get_data ((GSequencePtr)value); + dir_to_iters (data, dir_file_entry->reverse_map); +} + +GList * +fm_list_model_get_all_iters_for_file (FMListModel *model, NautilusFile *file) +{ + struct GetIters data; + + data.file = file; + data.model = model; + data.iters = NULL; + + dir_to_iters (&data, model->details->top_reverse_map); + g_hash_table_foreach (model->details->directory_reverse_map, + file_to_iter_cb, &data); + + return g_list_reverse (data.iters); +} + +gboolean +fm_list_model_get_first_iter_for_file (FMListModel *model, + NautilusFile *file, + GtkTreeIter *iter) +{ + GList *list; + gboolean res; + + res = FALSE; + + list = fm_list_model_get_all_iters_for_file (model, file); + if (list != NULL) { + res = TRUE; + *iter = *(GtkTreeIter *)list->data; + } + eel_g_list_free_deep (list); + + return res; +} + - ptr = g_hash_table_lookup (model->details->reverse_map, file); +gboolean +fm_list_model_get_tree_iter_from_file (FMListModel *model, NautilusFile *file, + NautilusDirectory *directory, + GtkTreeIter *iter) +{ + GSequencePtr ptr; + ptr = lookup_file (model, file, directory); if (!ptr) { return FALSE; } - g_assert (!g_sequence_ptr_is_end (ptr)); - g_assert (((FileEntry *)g_sequence_ptr_get_data (ptr))->file == file); - - if (iter != NULL) { - iter->stamp = model->details->stamp; - iter->user_data = ptr; - } + fm_list_model_ptr_to_iter (model, ptr, iter); return TRUE; } @@ -545,21 +648,13 @@ fm_list_model_file_entry_compare_func (gconstpointer a, return result; } -static int -fm_list_model_compare_func (gconstpointer a, - gconstpointer b, - gpointer user_data) +int +fm_list_model_compare_func (FMListModel *model, + NautilusFile *file1, + NautilusFile *file2) { - NautilusFile *file1; - NautilusFile *file2; - FMListModel *model; int result; - model = (FMListModel *)user_data; - - file1 = (NautilusFile *)a; - file2 = (NautilusFile *)b; - result = nautilus_file_compare_for_sort_by_attribute (file1, file2, model->details->sort_attribute, model->details->sort_directories_first, @@ -641,12 +736,6 @@ fm_list_model_sort (FMListModel *model) gtk_tree_path_free (path); } -void -fm_list_model_sort_files (FMListModel *model, GList **files) -{ - *files = g_list_sort_with_data (*files, fm_list_model_compare_func, model); -} - static gboolean fm_list_model_get_sort_column_id (GtkTreeSortable *sortable, gint *sort_column_id, @@ -716,7 +805,6 @@ each_path_get_data_binder (NautilusDragEachSelectedItemDataGet data_get, char *uri; GdkRectangle cell_area; GtkTreeViewColumn *column; - GtkTreeIter iter; info = context; @@ -728,31 +816,25 @@ each_path_get_data_binder (NautilusDragEachSelectedItemDataGet data_get, row = l->data; path = gtk_tree_row_reference_get_path (row); - - if (gtk_tree_model_get_iter (GTK_TREE_MODEL (info->model), - &iter, path)) { - gtk_tree_model_get (GTK_TREE_MODEL (info->model), - &iter, - FM_LIST_MODEL_FILE_COLUMN, &file, - -1); - - if (file) { - gtk_tree_view_get_cell_area - (info->model->details->drag_view, - path, - column, - &cell_area); + file = fm_list_model_file_for_path (info->model, path); + if (file) { + gtk_tree_view_get_cell_area + (info->model->details->drag_view, + path, + column, + &cell_area); - uri = nautilus_file_get_uri (file); + uri = nautilus_file_get_uri (file); - (*data_get) (uri, - 0, - cell_area.y - info->model->details->drag_begin_y, - cell_area.width, cell_area.height, - data); + (*data_get) (uri, + 0, + cell_area.y - info->model->details->drag_begin_y, + cell_area.width, cell_area.height, + data); - g_free (uri); - } + g_free (uri); + + nautilus_file_unref (file); } gtk_tree_path_free (path); @@ -822,87 +904,65 @@ add_dummy_row (FMListModel *model, FileEntry *parent_entry) } gboolean -fm_list_model_add_file (FMListModel *model, NautilusFile *file) +fm_list_model_add_file (FMListModel *model, NautilusFile *file, + NautilusDirectory *directory) { GtkTreeIter iter; GtkTreePath *path; FileEntry *file_entry; - NautilusFile *parent_file; GSequencePtr ptr, parent_ptr; GSequence *files; gboolean replace_dummy; + GHashTable *parent_hash; - /* We may only add each file once, in one dir. */ - ptr = g_hash_table_lookup (model->details->reverse_map, file); - if (ptr != NULL) { - file_entry = g_sequence_ptr_get_data (ptr); - - parent_file = nautilus_file_get_parent (file); - if (parent_file == NULL) { - return FALSE; - } - parent_ptr = g_hash_table_lookup (model->details->reverse_map, - parent_file); - nautilus_file_unref (parent_file); - if (/* toplevel parent */ - (file_entry->parent == NULL && parent_ptr == NULL) || - /* same in-tree parent */ - (file_entry->parent != NULL && parent_ptr != NULL && - file_entry->parent->ptr == parent_ptr) ) { - /* Don't add twice in same place */ - return FALSE; - } - - /* file has a new parent, due to a move - * this happens because a move results in a - * CHANGE event and an ADD event, and - * if the target directory of the move is - * added to the FMDirectoryView - * then we won't remove the changed file. - */ - fm_list_model_remove_file (model, file); - - /* Now add it back again in the new place. */ + parent_ptr = g_hash_table_lookup (model->details->directory_reverse_map, + directory); + if (parent_ptr) { + file_entry = g_sequence_ptr_get_data (parent_ptr); + ptr = g_hash_table_lookup (file_entry->reverse_map, file); + } else { + file_entry = NULL; + ptr = g_hash_table_lookup (model->details->top_reverse_map, file); } - nautilus_file_ref (file); + if (ptr != NULL) { + g_warning ("file already in tree (parent_ptr: %p)!!!\n", parent_ptr); + return FALSE; + } file_entry = g_new0 (FileEntry, 1); - file_entry->file = file; + file_entry->file = nautilus_file_ref (file); file_entry->parent = NULL; file_entry->subdirectory = NULL; file_entry->files = NULL; files = model->details->files; + parent_hash = model->details->top_reverse_map; replace_dummy = FALSE; - parent_file = nautilus_file_get_parent (file); - if (parent_file != NULL) { - parent_ptr = g_hash_table_lookup (model->details->reverse_map, - parent_file); - nautilus_file_unref (parent_file); - if (parent_ptr != NULL) { - file_entry->parent = g_sequence_ptr_get_data (parent_ptr); - files = file_entry->parent->files; - if (g_sequence_get_length (files) == 1) { - GSequencePtr dummy_ptr = g_sequence_get_ptr_at_pos (files, 0); - FileEntry *dummy_entry = g_sequence_ptr_get_data (dummy_ptr); - if (dummy_entry->file == NULL) { - /* replace the dummy loading entry */ - model->details->stamp++; - g_sequence_remove (dummy_ptr); - - replace_dummy = TRUE; - } + if (parent_ptr != NULL) { + file_entry->parent = g_sequence_ptr_get_data (parent_ptr); + parent_hash = file_entry->parent->reverse_map; + files = file_entry->parent->files; + if (g_sequence_get_length (files) == 1) { + GSequencePtr dummy_ptr = g_sequence_get_ptr_at_pos (files, 0); + FileEntry *dummy_entry = g_sequence_ptr_get_data (dummy_ptr); + if (dummy_entry->file == NULL) { + /* replace the dummy loading entry */ + model->details->stamp++; + g_sequence_remove (dummy_ptr); + + replace_dummy = TRUE; } } } + file_entry->ptr = g_sequence_insert_sorted (files, file_entry, fm_list_model_file_entry_compare_func, model); - g_hash_table_insert (model->details->reverse_map, file, file_entry->ptr); + g_hash_table_insert (parent_hash, file, file_entry->ptr); iter.stamp = model->details->stamp; iter.user_data = file_entry->ptr; @@ -928,23 +988,21 @@ fm_list_model_add_file (FMListModel *model, NautilusFile *file) } void -fm_list_model_file_changed (FMListModel *model, NautilusFile *file) +fm_list_model_file_changed (FMListModel *model, NautilusFile *file, + NautilusDirectory *directory) { GtkTreeIter iter; GtkTreePath *path; GSequencePtr ptr; - ptr = g_hash_table_lookup (model->details->reverse_map, file); + ptr = lookup_file (model, file, directory); if (!ptr) { return; } g_sequence_ptr_sort_changed (ptr, fm_list_model_file_entry_compare_func, model); - if (!fm_list_model_get_tree_iter_from_file (model, file, &iter)) { - return; - } - + fm_list_model_ptr_to_iter (model, ptr, &iter); path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter); gtk_tree_model_row_changed (GTK_TREE_MODEL (model), path, &iter); gtk_tree_path_free (path); @@ -979,7 +1037,8 @@ fm_list_model_remove (FMListModel *model, GtkTreeIter *iter) child_file_entry = g_sequence_ptr_get_data (child_ptr); if (child_file_entry->file != NULL) { fm_list_model_remove_file (model, - child_file_entry->file); + child_file_entry->file, + file_entry->subdirectory); } else { path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), iter); gtk_tree_path_append_index (path, 0); @@ -995,7 +1054,11 @@ fm_list_model_remove (FMListModel *model, GtkTreeIter *iter) } - g_hash_table_remove (model->details->reverse_map, file_entry->file); + if (file_entry->parent != NULL) { + g_hash_table_remove (file_entry->parent->reverse_map, file_entry->file); + } else { + g_hash_table_remove (model->details->top_reverse_map, file_entry->file); + } parent_file_entry = file_entry->parent; if (parent_file_entry && g_sequence_get_length (parent_file_entry->files) == 1 && @@ -1011,6 +1074,8 @@ fm_list_model_remove (FMListModel *model, GtkTreeIter *iter) g_signal_emit (model, list_model_signals[SUBDIRECTORY_UNLOADED], 0, file_entry->subdirectory); + g_hash_table_remove (model->details->directory_reverse_map, + file_entry->subdirectory); } path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), iter); @@ -1032,11 +1097,12 @@ fm_list_model_remove (FMListModel *model, GtkTreeIter *iter) } void -fm_list_model_remove_file (FMListModel *model, NautilusFile *file) +fm_list_model_remove_file (FMListModel *model, NautilusFile *file, + NautilusDirectory *directory) { GtkTreeIter iter; - if (fm_list_model_get_tree_iter_from_file (model, file, &iter)) { + if (fm_list_model_get_tree_iter_from_file (model, file, directory, &iter)) { fm_list_model_remove (model, &iter); } } @@ -1090,6 +1156,7 @@ fm_list_model_load_subdirectory (FMListModel *model, GtkTreePath *path, Nautilus { GtkTreeIter iter; FileEntry *file_entry; + NautilusDirectory *subdirectory; if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path)) { return FALSE; @@ -1101,9 +1168,23 @@ fm_list_model_load_subdirectory (FMListModel *model, GtkTreePath *path, Nautilus return FALSE; } - file_entry->subdirectory = nautilus_directory_get_for_file (file_entry->file); - nautilus_directory_ref (file_entry->subdirectory); - *directory = file_entry->subdirectory; + subdirectory = nautilus_directory_get_for_file (file_entry->file); + + if (g_hash_table_lookup (model->details->directory_reverse_map, + subdirectory) != NULL) { + nautilus_directory_unref (subdirectory); + g_warning ("Already in directory_reverse_map, failing\n"); + return FALSE; + } + + file_entry->subdirectory = subdirectory, + g_hash_table_insert (model->details->directory_reverse_map, + subdirectory, file_entry->ptr); + file_entry->reverse_map = g_hash_table_new (g_direct_hash, g_direct_equal); + + /* Return a ref too */ + nautilus_directory_ref (subdirectory); + *directory = subdirectory; return TRUE; } @@ -1114,7 +1195,8 @@ fm_list_model_unload_subdirectory (FMListModel *model, GtkTreeIter *iter) { GSequencePtr child_ptr; FileEntry *file_entry, *child_file_entry; - + GtkTreeIter child_iter; + file_entry = g_sequence_ptr_get_data (iter->user_data); if (file_entry->file == NULL || file_entry->subdirectory == NULL) { @@ -1131,8 +1213,8 @@ fm_list_model_unload_subdirectory (FMListModel *model, GtkTreeIter *iter) /* Don't delete the dummy node */ break; } else { - fm_list_model_remove_file (model, - child_file_entry->file); + fm_list_model_ptr_to_iter (model, child_ptr, &child_iter); + fm_list_model_remove (model, &child_iter); } } @@ -1142,8 +1224,14 @@ fm_list_model_unload_subdirectory (FMListModel *model, GtkTreeIter *iter) file_entry->subdirectory); /* actually unload */ + g_hash_table_remove (model->details->directory_reverse_map, + file_entry->subdirectory); nautilus_directory_unref (file_entry->subdirectory); file_entry->subdirectory = NULL; + + g_assert (g_hash_table_size (file_entry->reverse_map) == 0); + g_hash_table_destroy (file_entry->reverse_map); + file_entry->reverse_map = NULL; } @@ -1386,9 +1474,13 @@ fm_list_model_dispose (GObject *object) model->details->files = NULL; } - if (model->details->reverse_map) { - g_hash_table_destroy (model->details->reverse_map); - model->details->reverse_map = NULL; + if (model->details->top_reverse_map) { + g_hash_table_destroy (model->details->top_reverse_map); + model->details->top_reverse_map = NULL; + } + if (model->details->directory_reverse_map) { + g_hash_table_destroy (model->details->directory_reverse_map); + model->details->directory_reverse_map = NULL; } EEL_CALL_PARENT (G_OBJECT_CLASS, dispose, (object)); @@ -1412,7 +1504,8 @@ fm_list_model_init (FMListModel *model) { model->details = g_new0 (FMListModelDetails, 1); model->details->files = g_sequence_new ((GDestroyNotify)file_entry_free); - model->details->reverse_map = g_hash_table_new (g_direct_hash, g_direct_equal); + model->details->top_reverse_map = g_hash_table_new (g_direct_hash, g_direct_equal); + model->details->directory_reverse_map = g_hash_table_new (g_direct_hash, g_direct_equal); model->details->stamp = g_random_int (); model->details->sort_attribute = NULL; model->details->columns = g_ptr_array_new (); @@ -1526,7 +1619,7 @@ fm_list_model_get_type (void) struct ChangeDummyData { FMListModel *model; - NautilusFile *file; + NautilusDirectory *directory; }; static gboolean @@ -1545,8 +1638,8 @@ change_dummy_row_callback (gpointer callback_data) if (data->model != NULL) { model = data->model; - parent_ptr = g_hash_table_lookup (model->details->reverse_map, - data->file); + parent_ptr = g_hash_table_lookup (model->details->directory_reverse_map, + data->directory); file_entry = g_sequence_ptr_get_data (parent_ptr); file_entry->loaded = 1; @@ -1569,7 +1662,7 @@ change_dummy_row_callback (gpointer callback_data) } eel_remove_weak_pointer (&data->model); - nautilus_file_unref (data->file); + nautilus_directory_unref (data->directory); g_free (data); return FALSE; @@ -1578,15 +1671,12 @@ change_dummy_row_callback (gpointer callback_data) void fm_list_model_subdirectory_done_loading (FMListModel *model, NautilusDirectory *directory) { - NautilusFile *parent_file; GSequencePtr parent_ptr; struct ChangeDummyData *data; - parent_file = nautilus_directory_get_corresponding_file (directory); - parent_ptr = g_hash_table_lookup (model->details->reverse_map, - parent_file); + parent_ptr = g_hash_table_lookup (model->details->directory_reverse_map, + directory); if (parent_ptr == NULL) { - nautilus_file_unref (parent_file); return; } @@ -1596,10 +1686,9 @@ fm_list_model_subdirectory_done_loading (FMListModel *model, NautilusDirectory * */ data = g_new (struct ChangeDummyData, 1); data->model = model; - data->file = nautilus_file_ref (parent_file); + data->directory = directory; + nautilus_directory_ref (directory); eel_add_weak_pointer (&data->model); g_timeout_add (LOADING_TO_EMPTY_DELAY, change_dummy_row_callback, data); - - nautilus_file_unref (parent_file); } diff --git a/src/file-manager/fm-list-model.h b/src/file-manager/fm-list-model.h index 6dcb9becf..809f24a8a 100644 --- a/src/file-manager/fm-list-model.h +++ b/src/file-manager/fm-list-model.h @@ -76,16 +76,25 @@ typedef struct { GType fm_list_model_get_type (void); gboolean fm_list_model_add_file (FMListModel *model, - NautilusFile *file); + NautilusFile *file, + NautilusDirectory *directory); void fm_list_model_file_changed (FMListModel *model, - NautilusFile *file); + NautilusFile *file, + NautilusDirectory *directory); gboolean fm_list_model_is_empty (FMListModel *model); guint fm_list_model_get_length (FMListModel *model); void fm_list_model_remove_file (FMListModel *model, - NautilusFile *file); + NautilusFile *file, + NautilusDirectory *directory); void fm_list_model_clear (FMListModel *model); gboolean fm_list_model_get_tree_iter_from_file (FMListModel *model, NautilusFile *file, + NautilusDirectory *directory, + GtkTreeIter *iter); +GList * fm_list_model_get_all_iters_for_file (FMListModel *model, + NautilusFile *file); +gboolean fm_list_model_get_first_iter_for_file (FMListModel *model, + NautilusFile *file, GtkTreeIter *iter); void fm_list_model_set_should_sort_directories_first (FMListModel *model, gboolean sort_directories_first); @@ -95,7 +104,7 @@ int fm_list_model_get_sort_column_id_from_attribute (FMListModel *model, const char *attribute); char *fm_list_model_get_attribute_from_sort_column_id (FMListModel *model, int sort_column_id); -void fm_list_model_sort_files (FMListModel *model, +void fm_list_model_sort_files (FMListModel *model, GList **files); NautilusZoomLevel fm_list_model_get_zoom_level_from_column_id (int column); @@ -114,6 +123,9 @@ void fm_list_model_set_drag_view (FMListModel *model, void fm_list_model_get_drag_types (const GtkTargetEntry **entries, int *num_entries); +int fm_list_model_compare_func (FMListModel *model, + NautilusFile *file1, + NautilusFile *file2); int fm_list_model_add_column (FMListModel *model, @@ -122,6 +134,6 @@ int fm_list_model_get_column_number (FMListModel *model, const char *column_name); void fm_list_model_subdirectory_done_loading (FMListModel *model, - NautilusDirectory *directory); + NautilusDirectory *directory); #endif /* FM_LIST_MODEL_H */ diff --git a/src/file-manager/fm-list-view.c b/src/file-manager/fm-list-view.c index 8d8f9669c..382e3c69a 100644 --- a/src/file-manager/fm-list-view.c +++ b/src/file-manager/fm-list-view.c @@ -912,6 +912,7 @@ row_expanded_callback (GtkTreeView *treeview, GtkTreeIter *iter, GtkTreePath *pa struct UnloadDelayData { NautilusFile *file; + NautilusDirectory *directory; FMListView *view; }; @@ -927,6 +928,7 @@ unload_file_timeout (gpointer data) model = unload_data->view->details->model; if (fm_list_model_get_tree_iter_from_file (model, unload_data->file, + unload_data->directory, &iter)) { path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter); if (!gtk_tree_view_row_expanded (unload_data->view->details->tree_view, @@ -939,8 +941,10 @@ unload_file_timeout (gpointer data) eel_remove_weak_pointer (&unload_data->view); - - g_object_unref (unload_data->file); + if (unload_data->directory) { + nautilus_directory_unref (unload_data->directory); + } + nautilus_file_unref (unload_data->file); g_free (unload_data); return FALSE; } @@ -950,18 +954,29 @@ row_collapsed_callback (GtkTreeView *treeview, GtkTreeIter *iter, GtkTreePath *p { FMListView *view; NautilusFile *file; + NautilusDirectory *directory; + GtkTreeIter parent; struct UnloadDelayData *unload_data; + GtkTreeModel *model; view = FM_LIST_VIEW (callback_data); + model = GTK_TREE_MODEL (view->details->model); - gtk_tree_model_get (GTK_TREE_MODEL (view->details->model), - iter, + gtk_tree_model_get (model, iter, FM_LIST_MODEL_FILE_COLUMN, &file, -1); + + directory = NULL; + if (gtk_tree_model_iter_parent (model, &parent, iter)) { + gtk_tree_model_get (model, &parent, + FM_LIST_MODEL_SUBDIRECTORY_COLUMN, &directory, + -1); + } unload_data = g_new (struct UnloadDelayData, 1); unload_data->view = view; unload_data->file = file; + unload_data->directory = directory; eel_add_weak_pointer (&unload_data->view); @@ -1150,23 +1165,10 @@ get_file_for_path_callback (NautilusTreeViewDragDest *dest, gpointer user_data) { FMListView *view; - GtkTreeIter iter; - NautilusFile *file; view = FM_LIST_VIEW (user_data); - file = NULL; - - if (gtk_tree_model_get_iter (GTK_TREE_MODEL (view->details->model), - &iter, path)) { - gtk_tree_model_get (GTK_TREE_MODEL (view->details->model), - &iter, - FM_LIST_MODEL_FILE_COLUMN, - &file, - -1); - } - - return file; + return fm_list_model_file_for_path (view->details->model, path); } /* Handles an URL received from Mozilla */ @@ -1485,12 +1487,12 @@ create_and_set_up_tree_view (FMListView *view) } static void -fm_list_view_add_file (FMDirectoryView *view, NautilusFile *file) +fm_list_view_add_file (FMDirectoryView *view, NautilusFile *file, NautilusDirectory *directory) { FMListModel *model; - + model = FM_LIST_VIEW (view)->details->model; - fm_list_model_add_file (model, file); + fm_list_model_add_file (model, file, directory); } static GList * @@ -1661,9 +1663,9 @@ fm_list_view_clear (FMDirectoryView *view) } static void -fm_list_view_file_changed (FMDirectoryView *view, NautilusFile *file) +fm_list_view_file_changed (FMDirectoryView *view, NautilusFile *file, NautilusDirectory *directory) { - fm_list_model_file_changed (FM_LIST_VIEW (view)->details->model, file); + fm_list_model_file_changed (FM_LIST_VIEW (view)->details->model, file, directory); } static GtkWidget * @@ -1685,7 +1687,6 @@ fm_list_view_get_selection_foreach_func (GtkTreeModel *model, GtkTreePath *path, -1); if (file != NULL) { - nautilus_file_ref (file); (* list) = g_list_prepend ((* list), file); } } @@ -1784,7 +1785,7 @@ fm_list_view_end_file_changes (FMDirectoryView *view) } static void -fm_list_view_remove_file (FMDirectoryView *view, NautilusFile *file) +fm_list_view_remove_file (FMDirectoryView *view, NautilusFile *file, NautilusDirectory *directory) { GtkTreePath *path; GtkTreePath *file_path; @@ -1794,13 +1795,13 @@ fm_list_view_remove_file (FMDirectoryView *view, NautilusFile *file) FMListView *list_view; GtkTreeModel* tree_model; GtkTreeSelection *selection; - + path = NULL; row_reference = NULL; list_view = FM_LIST_VIEW (view); tree_model = GTK_TREE_MODEL(list_view->details->model); - if(fm_list_model_get_tree_iter_from_file (list_view->details->model, file, &iter)) { + if (fm_list_model_get_tree_iter_from_file (list_view->details->model, file, directory, &iter)) { selection = gtk_tree_view_get_selection (list_view->details->tree_view); file_path = gtk_tree_model_get_path (tree_model, &iter); @@ -1825,7 +1826,7 @@ fm_list_view_remove_file (FMDirectoryView *view, NautilusFile *file) gtk_tree_path_free (file_path); - fm_list_model_remove_file (list_view->details->model, file); + fm_list_model_remove_file (list_view->details->model, file, directory); if (gtk_tree_row_reference_valid (row_reference)) { if (list_view->details->new_selection_path) { @@ -1834,7 +1835,7 @@ fm_list_view_remove_file (FMDirectoryView *view, NautilusFile *file) list_view->details->new_selection_path = gtk_tree_row_reference_get_path (row_reference); } - if(row_reference) { + if (row_reference) { gtk_tree_row_reference_free (row_reference); } } @@ -1848,7 +1849,7 @@ fm_list_view_set_selection (FMDirectoryView *view, GList *selection) FMListView *list_view; GtkTreeSelection *tree_selection; GList *node; - GtkTreeIter iter; + GList *iters, *l; NautilusFile *file; list_view = FM_LIST_VIEW (view); @@ -1859,9 +1860,13 @@ fm_list_view_set_selection (FMDirectoryView *view, GList *selection) gtk_tree_selection_unselect_all (tree_selection); for (node = selection; node != NULL; node = node->next) { file = node->data; - if (fm_list_model_get_tree_iter_from_file (list_view->details->model, file, &iter)) { - gtk_tree_selection_select_iter (tree_selection, &iter); + iters = fm_list_model_get_all_iters_for_file (list_view->details->model, file); + + for (l = iters; l != NULL; l = l->next) { + gtk_tree_selection_select_iter (tree_selection, + (GtkTreeIter *)l->data); } + eel_g_list_free_deep (iters); } g_signal_handlers_unblock_by_func (tree_selection, list_selection_changed_callback, view); @@ -1892,15 +1897,13 @@ fm_list_view_reveal_selection (FMDirectoryView *view) list_view = FM_LIST_VIEW (view); file = selection->data; - if (!fm_list_model_get_tree_iter_from_file (list_view->details->model, file, &iter)) { - return; - } - path = gtk_tree_model_get_path (GTK_TREE_MODEL (list_view->details->model), &iter); - - gtk_tree_view_scroll_to_cell (list_view->details->tree_view, path, NULL, FALSE, 0.0, 0.0); + if (fm_list_model_get_first_iter_for_file (list_view->details->model, file, &iter)) { + path = gtk_tree_model_get_path (GTK_TREE_MODEL (list_view->details->model), &iter); - gtk_tree_path_free (path); - path = NULL; + gtk_tree_view_scroll_to_cell (list_view->details->tree_view, path, NULL, FALSE, 0.0, 0.0); + + gtk_tree_path_free (path); + } } nautilus_file_list_free (selection); @@ -2299,7 +2302,7 @@ fm_list_view_start_renaming_file (FMDirectoryView *view, return; } - if (!fm_list_model_get_tree_iter_from_file (list_view->details->model, file, &iter)) { + if (!fm_list_model_get_first_iter_for_file (list_view->details->model, file, &iter)) { return; } @@ -2448,14 +2451,13 @@ fm_list_view_sort_directories_first_changed (FMDirectoryView *view) fm_directory_view_should_sort_directories_first (view)); } -static void -fm_list_view_sort_files (FMDirectoryView *view, GList **files) +static int +fm_list_view_compare_files (FMDirectoryView *view, NautilusFile *file1, NautilusFile *file2) { FMListView *list_view; list_view = FM_LIST_VIEW (view); - - fm_list_model_sort_files (list_view->details->model, files); + return fm_list_model_compare_func (list_view->details->model, file1, file2); } static void @@ -2573,7 +2575,7 @@ fm_list_view_scroll_to_file (FMListView *view, GtkTreePath *path; GtkTreeIter iter; - if (!fm_list_model_get_tree_iter_from_file (view->details->model, file, &iter)) { + if (!fm_list_model_get_first_iter_for_file (view->details->model, file, &iter)) { return; } @@ -2593,9 +2595,13 @@ list_view_scroll_to_file (NautilusView *view, NautilusFile *file; if (uri != NULL) { - file = nautilus_file_get (uri); - fm_list_view_scroll_to_file (FM_LIST_VIEW (view), file); - nautilus_file_unref (file); + /* Only if existing, since we don't want to add the file to + the directory if it has been removed since then */ + file = nautilus_file_get_existing (uri); + if (file != NULL) { + fm_list_view_scroll_to_file (FM_LIST_VIEW (view), file); + nautilus_file_unref (file); + } } } @@ -2631,7 +2637,7 @@ fm_list_view_class_init (FMListViewClass *class) fm_directory_view_class->reveal_selection = fm_list_view_reveal_selection; fm_directory_view_class->select_all = fm_list_view_select_all; fm_directory_view_class->set_selection = fm_list_view_set_selection; - fm_directory_view_class->sort_files = fm_list_view_sort_files; + fm_directory_view_class->compare_files = fm_list_view_compare_files; fm_directory_view_class->sort_directories_first_changed = fm_list_view_sort_directories_first_changed; fm_directory_view_class->start_renaming_file = fm_list_view_start_renaming_file; fm_directory_view_class->get_zoom_level = fm_list_view_get_zoom_level; |