summaryrefslogtreecommitdiff
path: root/src/file-manager
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2005-12-01 13:27:19 +0000
committerAlexander Larsson <alexl@src.gnome.org>2005-12-01 13:27:19 +0000
commit76bb34583a5ecd192c736b93a1b3dd9fed526302 (patch)
tree5aa4cb937ffbab4674fbb3720712d7aa23360c72 /src/file-manager
parente11a936656f6f23847dddaad47120b51c3c85fd9 (diff)
downloadnautilus-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.c284
-rw-r--r--src/file-manager/fm-directory-view.h17
-rw-r--r--src/file-manager/fm-icon-view.c58
-rw-r--r--src/file-manager/fm-list-model.c381
-rw-r--r--src/file-manager/fm-list-model.h22
-rw-r--r--src/file-manager/fm-list-view.c106
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;