diff options
Diffstat (limited to 'libnautilus-private')
-rw-r--r-- | libnautilus-private/Makefile.am | 2 | ||||
-rw-r--r-- | libnautilus-private/nautilus-background-canvas-group.c | 3 | ||||
-rw-r--r-- | libnautilus-private/nautilus-directory.c | 1 | ||||
-rw-r--r-- | libnautilus-private/nautilus-glib-extensions.c | 42 | ||||
-rw-r--r-- | libnautilus-private/nautilus-glib-extensions.h | 87 | ||||
-rw-r--r-- | libnautilus-private/nautilus-merged-directory.c | 553 | ||||
-rw-r--r-- | libnautilus-private/nautilus-merged-directory.h | 60 | ||||
-rw-r--r-- | libnautilus-private/nautilus-scalable-font.c | 2 | ||||
-rw-r--r-- | libnautilus-private/nautilus-trash-directory.c | 606 | ||||
-rw-r--r-- | libnautilus-private/nautilus-trash-directory.h | 20 |
10 files changed, 857 insertions, 519 deletions
diff --git a/libnautilus-private/Makefile.am b/libnautilus-private/Makefile.am index 91732d5db..6316fb8cb 100644 --- a/libnautilus-private/Makefile.am +++ b/libnautilus-private/Makefile.am @@ -86,6 +86,7 @@ libnautilus_extensions_la_SOURCES = \ nautilus-link.c \ nautilus-list-column-title.c \ nautilus-list.c \ + nautilus-merged-directory.c \ nautilus-mime-actions.c \ nautilus-password-dialog.c \ nautilus-preference.c \ @@ -172,6 +173,7 @@ noinst_HEADERS = \ nautilus-link.h \ nautilus-list-column-title.h \ nautilus-list.h \ + nautilus-merged-directory.h \ nautilus-metadata.h \ nautilus-mime-actions.h \ nautilus-password-dialog.h \ diff --git a/libnautilus-private/nautilus-background-canvas-group.c b/libnautilus-private/nautilus-background-canvas-group.c index 31f35f22b..247d842be 100644 --- a/libnautilus-private/nautilus-background-canvas-group.c +++ b/libnautilus-private/nautilus-background-canvas-group.c @@ -139,9 +139,6 @@ nautilus_background_canvas_group_render (GnomeCanvasItem *item, GnomeCanvasBuf * /* FIXME: Shouldn't nautilus_background_draw_aa do these? */ buffer->is_bg = FALSE; buffer->is_buf = TRUE; - } else { - /* FIXME: Why do we need this in this case? */ - gnome_canvas_buf_ensure_buf (buffer); } /* Call through to the GnomeCanvasGroup implementation, which will draw all diff --git a/libnautilus-private/nautilus-directory.c b/libnautilus-private/nautilus-directory.c index ade4219fc..02a8914c5 100644 --- a/libnautilus-private/nautilus-directory.c +++ b/libnautilus-private/nautilus-directory.c @@ -979,7 +979,6 @@ gboolean nautilus_directory_is_not_empty (NautilusDirectory *directory) { g_return_val_if_fail (NAUTILUS_IS_DIRECTORY (directory), FALSE); - g_return_val_if_fail (nautilus_directory_is_file_list_monitored (directory), FALSE); return NAUTILUS_CALL_VIRTUAL (NAUTILUS_DIRECTORY_CLASS, directory, diff --git a/libnautilus-private/nautilus-glib-extensions.c b/libnautilus-private/nautilus-glib-extensions.c index f2cb19268..9956ca98e 100644 --- a/libnautilus-private/nautilus-glib-extensions.c +++ b/libnautilus-private/nautilus-glib-extensions.c @@ -646,6 +646,48 @@ nautilus_g_hash_table_new_free_at_exit (GHashFunc hash_func, return hash_table; } +typedef struct { + GList *keys; + GList *values; +} FlattenedHashTable; + +static void +flatten_hash_table_element (gpointer key, gpointer value, gpointer callback_data) +{ + FlattenedHashTable *flattened_table; + + flattened_table = callback_data; + flattened_table->keys = g_list_prepend + (flattened_table->keys, key); + flattened_table->values = g_list_prepend + (flattened_table->values, value); +} + +void +nautilus_g_hash_table_safe_for_each (GHashTable *hash_table, + GHFunc callback, + gpointer callback_data) +{ + FlattenedHashTable flattened; + GList *p, *q; + + flattened.keys = NULL; + flattened.values = NULL; + + g_hash_table_foreach (hash_table, + flatten_hash_table_element, + &flattened); + + for (p = flattened.keys, q = flattened.values; + p != NULL; + p = p->next, q = q->next) { + (* callback) (p->data, q->data, callback_data); + } + + g_list_free (flattened.keys); + g_list_free (flattened.values); +} + #if !defined (NAUTILUS_OMIT_SELF_CHECK) static void diff --git a/libnautilus-private/nautilus-glib-extensions.h b/libnautilus-private/nautilus-glib-extensions.h index 84595eee8..b3ed8de53 100644 --- a/libnautilus-private/nautilus-glib-extensions.h +++ b/libnautilus-private/nautilus-glib-extensions.h @@ -52,64 +52,65 @@ typedef gboolean (* NautilusPredicateFunction) (gpointer data, gpointer callback_data); /* Date & time functions. */ -GDate * nautilus_g_date_new_tm (struct tm *time_pieces); -char * nautilus_strdup_strftime (const char *format, - struct tm *time_pieces); +GDate * nautilus_g_date_new_tm (struct tm *time_pieces); +char * nautilus_strdup_strftime (const char *format, + struct tm *time_pieces); /* GList functions. */ -gboolean nautilus_g_list_exactly_one_item (GList *list); -gboolean nautilus_g_list_more_than_one_item (GList *list); -gboolean nautilus_g_list_equal (GList *list_a, - GList *list_b); -GList * nautilus_g_list_copy (GList *list); -void nautilus_g_list_safe_for_each (GList *list, - GFunc function, - gpointer user_data); -GList * nautilus_g_list_partition (GList *list, - NautilusPredicateFunction predicate, - gpointer user_data, - GList **removed); -void nautilus_g_list_free_deep_custom (GList *list, - GFunc element_free_func, - gpointer user_data); +gboolean nautilus_g_list_exactly_one_item (GList *list); +gboolean nautilus_g_list_more_than_one_item (GList *list); +gboolean nautilus_g_list_equal (GList *list_a, + GList *list_b); +GList * nautilus_g_list_copy (GList *list); +void nautilus_g_list_safe_for_each (GList *list, + GFunc function, + gpointer user_data); +GList * nautilus_g_list_partition (GList *list, + NautilusPredicateFunction predicate, + gpointer user_data, + GList **removed); +void nautilus_g_list_free_deep_custom (GList *list, + GFunc element_free_func, + gpointer user_data); /* List functions for lists of g_free'able objects. */ -void nautilus_g_list_free_deep (GList *list); - - -void nautilus_g_slist_free_deep_custom (GSList *list, - GFunc element_free_func, - gpointer user_data); +void nautilus_g_list_free_deep (GList *list); +void nautilus_g_slist_free_deep_custom (GSList *list, + GFunc element_free_func, + gpointer user_data); /* List functions for slists of g_free'able objects. */ -void nautilus_g_slist_free_deep (GSList *list); +void nautilus_g_slist_free_deep (GSList *list); /* List functions for lists of C strings. */ -gboolean nautilus_g_str_list_equal (GList *str_list_a, - GList *str_list_b); -GList * nautilus_g_str_list_copy (GList *str_list); -GList * nautilus_g_str_list_sort (GList *str_list); -GList * nautilus_g_str_list_sort_case_insensitive (GList *str_list); +gboolean nautilus_g_str_list_equal (GList *str_list_a, + GList *str_list_b); +GList * nautilus_g_str_list_copy (GList *str_list); +GList * nautilus_g_str_list_sort (GList *str_list); +GList * nautilus_g_str_list_sort_case_insensitive (GList *str_list); /* GHashTable functions */ -GHashTable *nautilus_g_hash_table_new_free_at_exit (GHashFunc hash_func, - GCompareFunc key_compare_func, - const char *display_name); +GHashTable *nautilus_g_hash_table_new_free_at_exit (GHashFunc hash_function, + GCompareFunc key_compare_function, + const char *display_name); +void nautilus_g_hash_table_safe_for_each (GHashTable *hash_table, + GHFunc callback, + gpointer callback_data); /* GPtrArray functions */ -GPtrArray * nautilus_g_ptr_array_new_from_list (GList *list); -void nautilus_g_ptr_array_sort (GPtrArray *array, - NautilusCompareFunction compare_callback, - gpointer callback_data); -int nautilus_g_ptr_array_search (GPtrArray *array, - NautilusSearchFunction search_callback, - gpointer callback_data, - gboolean match_only); +GPtrArray * nautilus_g_ptr_array_new_from_list (GList *list); +void nautilus_g_ptr_array_sort (GPtrArray *array, + NautilusCompareFunction compare_callback, + gpointer callback_data); +int nautilus_g_ptr_array_search (GPtrArray *array, + NautilusSearchFunction search_callback, + gpointer callback_data, + gboolean match_only); /* NULL terminated string arrays (strv). */ -int nautilus_g_strv_find (char **strv, - const char *find_me); +int nautilus_g_strv_find (char **strv, + const char *find_me); /* return the time in microseconds since the machine was started */ gint64 nautilus_get_system_time (void); diff --git a/libnautilus-private/nautilus-merged-directory.c b/libnautilus-private/nautilus-merged-directory.c new file mode 100644 index 000000000..b3c268efd --- /dev/null +++ b/libnautilus-private/nautilus-merged-directory.c @@ -0,0 +1,553 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- + + nautilus-merged-directory.c: Subclass of NautilusDirectory to implement the + virtual merged directory. + + Copyright (C) 1999, 2000 Eazel, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Author: Darin Adler <darin@eazel.com> +*/ + +#include <config.h> +#include "nautilus-merged-directory.h" + +#include "nautilus-directory-private.h" +#include "nautilus-file.h" +#include "nautilus-glib-extensions.h" +#include "nautilus-gtk-macros.h" +#include <gtk/gtksignal.h> + +struct NautilusMergedDirectoryDetails { + GList *directories; + GHashTable *callbacks; + GHashTable *monitors; +}; + +typedef struct { + /* Basic configuration. */ + NautilusMergedDirectory *merged; + NautilusDirectoryCallback callback; + gpointer callback_data; + + GList *wait_for_attributes; + gboolean wait_for_metadata; + + GList *non_ready_directories; + GList *merged_file_list; +} MergedCallback; + +typedef struct { + NautilusMergedDirectory *merged; + + GList *monitor_attributes; + gboolean monitor_metadata; + gboolean force_reload; +} MergedMonitor; + +static void nautilus_merged_directory_initialize (gpointer object, + gpointer klass); +static void nautilus_merged_directory_initialize_class (gpointer klass); +static void remove_all_real_directories (NautilusMergedDirectory *merged); +static guint merged_callback_hash (gconstpointer merged_callback); +static gboolean merged_callback_equal (gconstpointer merged_callback, + gconstpointer merged_callback_2); + +NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusMergedDirectory, + nautilus_merged_directory, + NAUTILUS_TYPE_DIRECTORY) + +static void +nautilus_merged_directory_initialize (gpointer object, gpointer klass) +{ + NautilusMergedDirectory *merged; + + merged = NAUTILUS_MERGED_DIRECTORY (object); + + merged->details = g_new0 (NautilusMergedDirectoryDetails, 1); + merged->details->callbacks = g_hash_table_new + (merged_callback_hash, merged_callback_equal); + merged->details->monitors = g_hash_table_new + (g_direct_hash, g_direct_equal); +} + +static void +merged_destroy (GtkObject *object) +{ + NautilusMergedDirectory *merged; + + merged = NAUTILUS_MERGED_DIRECTORY (object); + + remove_all_real_directories (merged); + + if (g_hash_table_size (merged->details->callbacks) != 0) { + g_warning ("call_when_ready still pending when merged virtual directory is destroyed"); + } + if (g_hash_table_size (merged->details->monitors) != 0) { + g_warning ("file monitor still active when merged virtual directory is destroyed"); + } + + g_hash_table_destroy (merged->details->callbacks); + g_hash_table_destroy (merged->details->monitors); + g_free (merged->details); + + NAUTILUS_CALL_PARENT_CLASS (GTK_OBJECT_CLASS, destroy, (object)); +} + +static guint +merged_callback_hash (gconstpointer merged_callback_as_pointer) +{ + const MergedCallback *merged_callback; + + merged_callback = merged_callback_as_pointer; + return GPOINTER_TO_UINT (merged_callback->callback) + ^ GPOINTER_TO_UINT (merged_callback->callback_data); +} + +static gboolean +merged_callback_equal (gconstpointer merged_callback_as_pointer, + gconstpointer merged_callback_as_pointer_2) +{ + const MergedCallback *merged_callback, *merged_callback_2; + + merged_callback = merged_callback_as_pointer; + merged_callback_2 = merged_callback_as_pointer_2; + + return merged_callback->callback == merged_callback_2->callback + && merged_callback->callback_data == merged_callback_2->callback_data; +} + +/* Return true if any directory in the list does. */ +static gboolean +merged_contains_file (NautilusDirectory *directory, + NautilusFile *file) +{ + NautilusMergedDirectory *merged; + GList *p; + + merged = NAUTILUS_MERGED_DIRECTORY (directory); + + for (p = merged->details->directories; p != NULL; p = p->next) { + if (nautilus_directory_contains_file (p->data, file)) { + return TRUE; + } + } + return FALSE; +} + +static void +merged_callback_destroy (MergedCallback *merged_callback) +{ + g_assert (merged_callback != NULL); + g_assert (NAUTILUS_IS_MERGED_DIRECTORY (merged_callback->merged)); + + nautilus_g_list_free_deep (merged_callback->wait_for_attributes); + g_list_free (merged_callback->non_ready_directories); + nautilus_file_list_free (merged_callback->merged_file_list); + g_free (merged_callback); +} + +static void +merged_callback_check_done (MergedCallback *merged_callback) +{ + /* Check if we are ready. */ + if (merged_callback->non_ready_directories != NULL) { + return; + } + + /* Remove from the hash table before sending it. */ + g_hash_table_remove (merged_callback->merged->details->callbacks, merged_callback); + + /* We are ready, so do the real callback. */ + (* merged_callback->callback) (NAUTILUS_DIRECTORY (merged_callback->merged), + merged_callback->merged_file_list, + merged_callback->callback_data); + + /* And we are done. */ + merged_callback_destroy (merged_callback); +} + +static void +merged_callback_remove_directory (MergedCallback *merged_callback, + NautilusDirectory *directory) +{ + merged_callback->non_ready_directories = g_list_remove + (merged_callback->non_ready_directories, + directory); + + /* Check if we are ready. */ + merged_callback_check_done (merged_callback); +} + +static void +directory_ready_callback (NautilusDirectory *directory, + GList *files, + gpointer callback_data) +{ + MergedCallback *merged_callback; + + g_assert (NAUTILUS_IS_DIRECTORY (directory)); + g_assert (callback_data != NULL); + + merged_callback = callback_data; + g_assert (g_list_find (merged_callback->non_ready_directories, directory) != NULL); + + /* Update based on this call. */ + merged_callback->merged_file_list = g_list_concat + (merged_callback->merged_file_list, + nautilus_file_list_copy (files)); + + /* Check if we are ready. */ + merged_callback_remove_directory (merged_callback, + directory); +} + +static void +merged_callback_connect_directory (MergedCallback *merged_callback, + NautilusDirectory *real_merged) +{ + nautilus_directory_call_when_ready + (real_merged, + merged_callback->wait_for_attributes, + merged_callback->wait_for_metadata, + directory_ready_callback, merged_callback); +} + +static void +merged_call_when_ready (NautilusDirectory *directory, + GList *file_attributes, + gboolean wait_for_metadata, + NautilusDirectoryCallback callback, + gpointer callback_data) +{ + NautilusMergedDirectory *merged; + MergedCallback search_key, *merged_callback; + GList *p; + + merged = NAUTILUS_MERGED_DIRECTORY (directory); + + /* Check to be sure we aren't overwriting. */ + search_key.callback = callback; + search_key.callback_data = callback_data; + if (g_hash_table_lookup (merged->details->callbacks, &search_key) != NULL) { + g_warning ("tried to add a new callback while an old one was pending"); + return; + } + + /* Create a merged_callback record. */ + merged_callback = g_new0 (MergedCallback, 1); + merged_callback->merged = merged; + merged_callback->callback = callback; + merged_callback->callback_data = callback_data; + merged_callback->wait_for_attributes = nautilus_g_str_list_copy (file_attributes); + merged_callback->wait_for_metadata = wait_for_metadata; + for (p = merged->details->directories; p != NULL; p = p->next) { + merged_callback->non_ready_directories = g_list_prepend + (merged_callback->non_ready_directories, p->data); + } + + /* Put it in the hash table. */ + g_hash_table_insert (merged->details->callbacks, + merged_callback, merged_callback); + + /* Handle the pathological case where there are no directories. */ + if (merged->details->directories == NULL) { + merged_callback_check_done (merged_callback); + } + + /* Now tell all the directories about it. */ + for (p = merged->details->directories; p != NULL; p = p->next) { + merged_callback_connect_directory (merged_callback, p->data); + } +} + +static void +merged_cancel_callback (NautilusDirectory *directory, + NautilusDirectoryCallback callback, + gpointer callback_data) +{ + NautilusMergedDirectory *merged; + MergedCallback search_key, *merged_callback; + GList *p; + + merged = NAUTILUS_MERGED_DIRECTORY (directory); + + /* Find the entry in the table. */ + search_key.callback = callback; + search_key.callback_data = callback_data; + merged_callback = g_hash_table_lookup (merged->details->callbacks, &search_key); + if (merged_callback == NULL) { + return; + } + + /* Remove from the hash table before working with it. */ + g_hash_table_remove (merged_callback->merged->details->callbacks, merged_callback); + + /* Tell all the directories to cancel the call. */ + for (p = merged_callback->non_ready_directories; p != NULL; p = p->next) { + nautilus_directory_cancel_callback + (p->data, + directory_ready_callback, merged_callback); + } + merged_callback_destroy (merged_callback); +} + +/* Create a monitor on each of the directories in the list. */ +static void +merged_file_monitor_add (NautilusDirectory *directory, + gconstpointer client, + GList *file_attributes, + gboolean monitor_metadata, + gboolean force_reload) +{ + NautilusMergedDirectory *merged; + MergedMonitor *monitor; + GList *p; + + merged = NAUTILUS_MERGED_DIRECTORY (directory); + + /* Map the client to a unique value so this doesn't interfere + * with direct monitoring of the directory by the same client. + */ + monitor = g_hash_table_lookup (merged->details->monitors, client); + if (monitor != NULL) { + g_assert (monitor->merged == merged); + nautilus_g_list_free_deep (monitor->monitor_attributes); + } else { + monitor = g_new0 (MergedMonitor, 1); + monitor->merged = merged; + g_hash_table_insert (merged->details->monitors, + (gpointer) client, monitor); + } + monitor->monitor_attributes = nautilus_g_str_list_copy (file_attributes); + monitor->monitor_metadata = monitor_metadata; + monitor->force_reload = force_reload; + + /* Call through to the real directory add calls. */ + for (p = merged->details->directories; p != NULL; p = p->next) { + nautilus_directory_file_monitor_add + (p->data, monitor, + file_attributes, monitor_metadata, force_reload); + } +} + +/* Remove the monitor from each of the directories in the list. */ +static void +merged_file_monitor_remove (NautilusDirectory *directory, + gconstpointer client) +{ + NautilusMergedDirectory *merged; + MergedMonitor *monitor; + GList *p; + + merged = NAUTILUS_MERGED_DIRECTORY (directory); + + /* Map the client to the value used by the earlier add call. */ + monitor = g_hash_table_lookup (merged->details->monitors, client); + if (monitor == NULL) { + return; + } + g_hash_table_remove (merged->details->monitors, client); + + /* Call through to the real directory remove calls. */ + for (p = merged->details->directories; p != NULL; p = p->next) { + nautilus_directory_file_monitor_remove + (p->data, monitor); + } + + nautilus_g_list_free_deep (monitor->monitor_attributes); + g_free (monitor); +} + +/* Return true only if all directories in the list do. */ +static gboolean +merged_are_all_files_seen (NautilusDirectory *directory) +{ + NautilusMergedDirectory *merged; + GList *p; + + merged = NAUTILUS_MERGED_DIRECTORY (directory); + + for (p = merged->details->directories; p != NULL; p = p->next) { + if (!nautilus_directory_are_all_files_seen (p->data)) { + return FALSE; + } + } + return TRUE; +} + +/* Return true if any directory in the list does. */ +static gboolean +merged_is_not_empty (NautilusDirectory *directory) +{ + NautilusMergedDirectory *merged; + GList *p; + + merged = NAUTILUS_MERGED_DIRECTORY (directory); + + for (p = merged->details->directories; p != NULL; p = p->next) { + if (nautilus_directory_is_not_empty (p->data)) { + return TRUE; + } + } + return FALSE; +} + +static void +nautilus_merged_directory_initialize_class (gpointer klass) +{ + GtkObjectClass *object_class; + NautilusDirectoryClass *directory_class; + + object_class = GTK_OBJECT_CLASS (klass); + directory_class = NAUTILUS_DIRECTORY_CLASS (klass); + + object_class->destroy = merged_destroy; + + directory_class->contains_file = merged_contains_file; + directory_class->call_when_ready = merged_call_when_ready; + directory_class->cancel_callback = merged_cancel_callback; + directory_class->file_monitor_add = merged_file_monitor_add; + directory_class->file_monitor_remove = merged_file_monitor_remove; + directory_class->are_all_files_seen = merged_are_all_files_seen; + directory_class->is_not_empty = merged_is_not_empty; +} + +static void +forward_files_added_cover (NautilusDirectory *real_directory, + GList *files, + NautilusMergedDirectory *merged) +{ + nautilus_directory_emit_files_added (NAUTILUS_DIRECTORY (merged), files); +} + +static void +forward_files_changed_cover (NautilusDirectory *real_directory, + GList *files, + NautilusMergedDirectory *merged) +{ + nautilus_directory_emit_files_changed (NAUTILUS_DIRECTORY (merged), files); +} + +static void +monitor_add_directory (gpointer key, + gpointer value, + gpointer callback_data) +{ + MergedMonitor *monitor; + + monitor = value; + nautilus_directory_file_monitor_add + (NAUTILUS_DIRECTORY (callback_data), monitor, + monitor->monitor_attributes, + monitor->monitor_metadata, + monitor->force_reload); +} + +void +nautilus_merged_directory_add_real_directory (NautilusMergedDirectory *merged, + NautilusDirectory *real_directory) +{ + g_return_if_fail (NAUTILUS_IS_MERGED_DIRECTORY (merged)); + g_return_if_fail (NAUTILUS_IS_DIRECTORY (real_directory)); + g_return_if_fail (!NAUTILUS_IS_MERGED_DIRECTORY (real_directory)); + + /* Quietly do nothing if asked to add something that's already there. */ + if (g_list_find (merged->details->directories, real_directory) != NULL) { + return; + } + + /* Add to our list of directories. */ + nautilus_directory_ref (real_directory); + merged->details->directories = g_list_prepend + (merged->details->directories, real_directory); + + /* Connect signals. */ + gtk_signal_connect (GTK_OBJECT (real_directory), + "files_added", + forward_files_added_cover, + merged); + gtk_signal_connect (GTK_OBJECT (real_directory), + "files_changed", + forward_files_changed_cover, + merged); + /* FIXME: Hook up the done_loading signal too? */ + + /* Add the directory to any extant monitors. */ + g_hash_table_foreach (merged->details->monitors, + monitor_add_directory, + real_directory); + /* FIXME: Do we need to add the directory to callbacks too? */ +} + +static void +merged_callback_remove_directory_cover (gpointer key, + gpointer value, + gpointer callback_data) +{ + merged_callback_remove_directory + (value, NAUTILUS_DIRECTORY (callback_data)); +} + +static void +monitor_remove_directory (gpointer key, + gpointer value, + gpointer callback_data) +{ + nautilus_directory_file_monitor_remove + (NAUTILUS_DIRECTORY (callback_data), value); +} + +void +nautilus_merged_directory_remove_real_directory (NautilusMergedDirectory *merged, + NautilusDirectory *real_directory) +{ + g_return_if_fail (NAUTILUS_IS_MERGED_DIRECTORY (merged)); + g_return_if_fail (NAUTILUS_IS_DIRECTORY (real_directory)); + + /* Quietly do nothing if asked to remove something that's not there. */ + if (g_list_find (merged->details->directories, real_directory) == NULL) { + return; + } + + /* Remove this directory from callbacks and monitors. */ + nautilus_g_hash_table_safe_for_each + (merged->details->callbacks, + merged_callback_remove_directory_cover, + real_directory); + g_hash_table_foreach + (merged->details->monitors, + monitor_remove_directory, + real_directory); + + /* Disconnect all the signals. */ + gtk_signal_disconnect_by_data (GTK_OBJECT (real_directory), merged); + + /* Remove from our list of directories. */ + merged->details->directories = g_list_remove + (merged->details->directories, real_directory); + nautilus_directory_unref (real_directory); +} + +static void +remove_all_real_directories (NautilusMergedDirectory *merged) +{ + while (merged->details->directories != NULL) { + nautilus_merged_directory_remove_real_directory + (merged, merged->details->directories->data); + } +} diff --git a/libnautilus-private/nautilus-merged-directory.h b/libnautilus-private/nautilus-merged-directory.h new file mode 100644 index 000000000..4b1f0152d --- /dev/null +++ b/libnautilus-private/nautilus-merged-directory.h @@ -0,0 +1,60 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- + + nautilus-merged-directory.h: Subclass of NautilusDirectory to implement + a virtual directory consisting of the merged contents of some real + directories. + + Copyright (C) 1999, 2000 Eazel, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Author: Darin Adler <darin@eazel.com> +*/ + +#ifndef NAUTILUS_MERGED_DIRECTORY_H +#define NAUTILUS_MERGED_DIRECTORY_H + +#include "nautilus-directory.h" + +#define NAUTILUS_TYPE_MERGED_DIRECTORY \ + (nautilus_merged_directory_get_type ()) +#define NAUTILUS_MERGED_DIRECTORY(obj) \ + (GTK_CHECK_CAST ((obj), NAUTILUS_TYPE_MERGED_DIRECTORY, NautilusMergedDirectory)) +#define NAUTILUS_MERGED_DIRECTORY_CLASS(klass) \ + (GTK_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_MERGED_DIRECTORY, NautilusMergedDirectoryClass)) +#define NAUTILUS_IS_MERGED_DIRECTORY(obj) \ + (GTK_CHECK_TYPE ((obj), NAUTILUS_TYPE_MERGED_DIRECTORY)) +#define NAUTILUS_IS_MERGED_DIRECTORY_CLASS(klass) \ + (GTK_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_MERGED_DIRECTORY)) + +typedef struct NautilusMergedDirectoryDetails NautilusMergedDirectoryDetails; + +typedef struct { + NautilusDirectory parent_slot; + NautilusMergedDirectoryDetails *details; +} NautilusMergedDirectory; + +typedef struct { + NautilusDirectoryClass parent_slot; +} NautilusMergedDirectoryClass; + +GtkType nautilus_merged_directory_get_type (void); +void nautilus_merged_directory_add_real_directory (NautilusMergedDirectory *merged_directory, + NautilusDirectory *real_directory); +void nautilus_merged_directory_remove_real_directory (NautilusMergedDirectory *merged_directory, + NautilusDirectory *real_directory); + +#endif /* NAUTILUS_MERGED_DIRECTORY_H */ diff --git a/libnautilus-private/nautilus-scalable-font.c b/libnautilus-private/nautilus-scalable-font.c index 293c71132..74ac1a727 100644 --- a/libnautilus-private/nautilus-scalable-font.c +++ b/libnautilus-private/nautilus-scalable-font.c @@ -710,7 +710,7 @@ nautilus_scalable_font_largest_fitting_font_size (const NautilusScalableFont *f g_return_val_if_fail (font_sizes != NULL, 0); g_return_val_if_fail (num_font_sizes > 0, 0); - if (text == NULL || available_width < 1) { + if (text == NULL || text[0] == '\0' || available_width < 1) { return font_sizes[num_font_sizes - 1]; } diff --git a/libnautilus-private/nautilus-trash-directory.c b/libnautilus-private/nautilus-trash-directory.c index 837bd8ef4..9d5fcbe91 100644 --- a/libnautilus-private/nautilus-trash-directory.c +++ b/libnautilus-private/nautilus-trash-directory.c @@ -30,556 +30,248 @@ #include "nautilus-file.h" #include "nautilus-glib-extensions.h" #include "nautilus-gtk-macros.h" +#include "nautilus-volume-monitor.h" #include <gtk/gtksignal.h> struct NautilusTrashDirectoryDetails { - GList *directories; - GHashTable *callbacks; - GHashTable *monitors; + GHashTable *volumes; }; typedef struct { - /* Basic configuration. */ NautilusTrashDirectory *trash; - NautilusDirectoryCallback callback; - gpointer callback_data; + NautilusVolume *volume; - GList *wait_for_attributes; - gboolean wait_for_metadata; - - GList *non_ready_directories; - GList *merged_file_list; -} TrashCallback; - -typedef struct { - NautilusTrashDirectory *trash; - - GList *monitor_attributes; - gboolean monitor_metadata; - gboolean force_reload; -} TrashMonitor; + GnomeVFSAsyncHandle *handle; + NautilusDirectory *real_directory; +} TrashVolume; static void nautilus_trash_directory_initialize (gpointer object, gpointer klass); static void nautilus_trash_directory_initialize_class (gpointer klass); -static void remove_all_real_directories (NautilusTrashDirectory *trash); -static guint trash_callback_hash (gconstpointer trash_callback); -static gboolean trash_callback_equal (gconstpointer trash_callback, - gconstpointer trash_callback_2); NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusTrashDirectory, nautilus_trash_directory, - NAUTILUS_TYPE_DIRECTORY) - -static void -nautilus_trash_directory_initialize (gpointer object, gpointer klass) -{ - NautilusTrashDirectory *trash; + NAUTILUS_TYPE_MERGED_DIRECTORY) - trash = NAUTILUS_TRASH_DIRECTORY (object); - - trash->details = g_new0 (NautilusTrashDirectoryDetails, 1); - trash->details->callbacks = g_hash_table_new - (trash_callback_hash, trash_callback_equal); - trash->details->monitors = g_hash_table_new - (g_direct_hash, g_direct_equal); -} - -static void -trash_destroy (GtkObject *object) +static GnomeVFSURI * +get_volume_vfs_uri_if_writable (NautilusVolume *volume) { - NautilusTrashDirectory *trash; - - trash = NAUTILUS_TRASH_DIRECTORY (object); - - remove_all_real_directories (trash); + char *uri; + GnomeVFSURI *vfs_uri; - if (g_hash_table_size (trash->details->callbacks) != 0) { - g_warning ("call_when_ready still pending when trash virtual directory is destroyed"); + if (volume->type != VOLUME_EXT2 || volume->is_read_only) { + return NULL; } - if (g_hash_table_size (trash->details->monitors) != 0) { - g_warning ("file monitor still active when trash virtual directory is destroyed"); - } - - g_hash_table_destroy (trash->details->callbacks); - g_hash_table_destroy (trash->details->monitors); - g_free (trash->details); - NAUTILUS_CALL_PARENT_CLASS (GTK_OBJECT_CLASS, destroy, (object)); -} - -static guint -trash_callback_hash (gconstpointer trash_callback_as_pointer) -{ - const TrashCallback *trash_callback; + uri = nautilus_get_uri_from_local_path (volume->mount_path); + vfs_uri = gnome_vfs_uri_new (uri); + g_free (uri); - trash_callback = trash_callback_as_pointer; - return GPOINTER_TO_UINT (trash_callback->callback) - ^ GPOINTER_TO_UINT (trash_callback->callback_data); + return vfs_uri; } -static gboolean -trash_callback_equal (gconstpointer trash_callback_as_pointer, - gconstpointer trash_callback_as_pointer_2) +static void +find_directory_callback (GnomeVFSAsyncHandle *handle, + GList *results, + gpointer callback_data) { - const TrashCallback *trash_callback, *trash_callback_2; - - trash_callback = trash_callback_as_pointer; - trash_callback_2 = trash_callback_as_pointer_2; - - return trash_callback->callback == trash_callback_2->callback - && trash_callback->callback_data == trash_callback_2->callback_data; -} + TrashVolume *trash_volume; + GnomeVFSFindDirectoryResult *result; + char *uri; + NautilusDirectory *directory; -/* Return true if any directory in the list does. */ -static gboolean -trash_contains_file (NautilusDirectory *directory, - NautilusFile *file) -{ - NautilusTrashDirectory *trash; - GList *p; + trash_volume = callback_data; - trash = NAUTILUS_TRASH_DIRECTORY (directory); + g_assert (nautilus_g_list_exactly_one_item (results)); + g_assert (trash_volume != NULL); + g_assert (NAUTILUS_IS_TRASH_DIRECTORY (trash_volume->trash)); + g_assert (trash_volume->real_directory == NULL); + g_assert (trash_volume->handle == handle); + + /* We are done with the async. I/O. */ + trash_volume->handle = NULL; - for (p = trash->details->directories; p != NULL; p = p->next) { - if (nautilus_directory_contains_file (p->data, file)) { - return TRUE; - } + /* If we can't find the trash, ignore it silently. */ + result = results->data; + if (result->result != GNOME_VFS_OK) { + return; } - return FALSE; -} - -static void -trash_callback_destroy (TrashCallback *trash_callback) -{ - g_assert (trash_callback != NULL); - g_assert (NAUTILUS_IS_TRASH_DIRECTORY (trash_callback->trash)); - - g_hash_table_remove (trash_callback->trash->details->callbacks, trash_callback); - nautilus_g_list_free_deep (trash_callback->wait_for_attributes); - g_list_free (trash_callback->non_ready_directories); - nautilus_file_list_free (trash_callback->merged_file_list); - g_free (trash_callback); -} -static void -trash_callback_check_done (TrashCallback *trash_callback) -{ - /* Check if we are ready. */ - if (trash_callback->non_ready_directories != NULL) { + /* If we can't make a directory object, ignore it silently. */ + uri = gnome_vfs_uri_to_string (result->uri, + GNOME_VFS_URI_HIDE_NONE); + directory = nautilus_directory_get (uri); + g_free (uri); + if (directory == NULL) { return; } - /* We are ready, so do the real callback. */ - (* trash_callback->callback) (NAUTILUS_DIRECTORY (trash_callback->trash), - trash_callback->merged_file_list, - trash_callback->callback_data); - - /* And we are done. */ - trash_callback_destroy (trash_callback); -} - -static void -trash_callback_remove_directory (TrashCallback *trash_callback, - NautilusDirectory *directory) -{ - trash_callback->non_ready_directories = g_list_remove - (trash_callback->non_ready_directories, + /* Add the directory object. */ + trash_volume->real_directory = directory; + nautilus_merged_directory_add_real_directory + (NAUTILUS_MERGED_DIRECTORY (trash_volume->trash), directory); - - /* Check if we are ready. */ - trash_callback_check_done (trash_callback); -} - -static void -directory_ready_callback (NautilusDirectory *directory, - GList *files, - gpointer callback_data) -{ - TrashCallback *trash_callback; - - g_assert (NAUTILUS_IS_DIRECTORY (directory)); - g_assert (callback_data != NULL); - - trash_callback = callback_data; - g_assert (g_list_find (trash_callback->non_ready_directories, directory) != NULL); - - /* Update based on this call. */ - trash_callback->merged_file_list = g_list_concat - (trash_callback->merged_file_list, - nautilus_file_list_copy (files)); - - /* Check if we are ready. */ - trash_callback_remove_directory (trash_callback, - directory); -} - -static void -trash_callback_connect_directory (TrashCallback *trash_callback, - NautilusDirectory *real_trash) -{ - nautilus_directory_call_when_ready - (real_trash, - trash_callback->wait_for_attributes, - trash_callback->wait_for_metadata, - directory_ready_callback, trash_callback); } static void -trash_call_when_ready (NautilusDirectory *directory, - GList *file_attributes, - gboolean wait_for_metadata, - NautilusDirectoryCallback callback, - gpointer callback_data) +add_volume (NautilusTrashDirectory *trash, + NautilusVolume *volume) { - NautilusTrashDirectory *trash; - TrashCallback search_key, *trash_callback; - GList *p; - - trash = NAUTILUS_TRASH_DIRECTORY (directory); - - /* Check to be sure we aren't overwriting. */ - search_key.callback = callback; - search_key.callback_data = callback_data; - if (g_hash_table_lookup (trash->details->callbacks, - &search_key) != NULL) { - g_warning ("tried to add a new callback while an old one was pending"); + TrashVolume *trash_volume; + GnomeVFSURI *vfs_uri; + GList vfs_uri_as_list; + + /* Quick out if we already know about this volume. */ + trash_volume = g_hash_table_lookup (trash->details->volumes, + volume); + if (trash_volume != NULL) { return; } - /* Create a trash_callback record. */ - trash_callback = g_new0 (TrashCallback, 1); - trash_callback->trash = trash; - trash_callback->callback = callback; - trash_callback->callback_data = callback_data; - trash_callback->wait_for_attributes = nautilus_g_str_list_copy (file_attributes); - trash_callback->wait_for_metadata = wait_for_metadata; - for (p = trash->details->directories; p != NULL; p = p->next) { - trash_callback->non_ready_directories = g_list_prepend - (trash_callback->non_ready_directories, p->data); - } - - /* Put it in the hash table. */ - g_hash_table_insert (trash->details->callbacks, trash_callback, trash_callback); - - /* Now tell all the directories about it. */ - for (p = trash->details->directories; p != NULL; p = p->next) { - trash_callback_connect_directory (trash_callback, p->data); - } - - /* Check just in case we are already done. */ - trash_callback_check_done (trash_callback); -} - -static void -trash_cancel_callback (NautilusDirectory *directory, - NautilusDirectoryCallback callback, - gpointer callback_data) -{ - NautilusTrashDirectory *trash; - TrashCallback search_key, *trash_callback; - GList *p; - - trash = NAUTILUS_TRASH_DIRECTORY (directory); - - /* Find the entry in the table. */ - search_key.callback = callback; - search_key.callback_data = callback_data; - trash_callback = g_hash_table_lookup - (trash->details->callbacks, &search_key); - if (trash_callback == NULL) { + /* If we can't get the URI, we jus don't do trash on this volume. */ + vfs_uri = get_volume_vfs_uri_if_writable (volume); + if (vfs_uri == NULL) { return; } - /* Tell all the directories to cancel the call. */ - for (p = trash_callback->non_ready_directories; p != NULL; p = p->next) { - nautilus_directory_cancel_callback - (p->data, - directory_ready_callback, trash_callback); - } - trash_callback_destroy (trash_callback); -} + /* Make the structure used to track the trash for this volume. */ + trash_volume = g_new0 (TrashVolume, 1); + trash_volume->trash = trash; + trash_volume->volume = volume; + g_hash_table_insert (trash->details->volumes, volume, trash_volume); -/* Create a monitor on each of the directories in the list. */ -static void -trash_file_monitor_add (NautilusDirectory *directory, - gconstpointer client, - GList *file_attributes, - gboolean monitor_metadata, - gboolean force_reload) -{ - NautilusTrashDirectory *trash; - gpointer unique_client; - GList *p; - - trash = NAUTILUS_TRASH_DIRECTORY (directory); - - /* Map the client to a unique value so this doesn't interfere - * with direct monitoring of the directory by the same client. - */ - unique_client = g_hash_table_lookup - (trash->details->monitors, client); - if (unique_client == NULL) { - unique_client = g_new (char, 1); - g_hash_table_insert (trash->details->monitors, - (gpointer) client, unique_client); - } - - /* Call through to the real directory add calls. */ - for (p = trash->details->directories; p != NULL; p = p->next) { - nautilus_directory_file_monitor_add - (p->data, unique_client, - file_attributes, monitor_metadata, force_reload); - } + /* Find the real trash directory for this one. */ + vfs_uri_as_list.data = vfs_uri; + vfs_uri_as_list.next = NULL; + vfs_uri_as_list.prev = NULL; + gnome_vfs_async_find_directory + (&trash_volume->handle, &vfs_uri_as_list, + GNOME_VFS_DIRECTORY_KIND_TRASH, TRUE, TRUE, 0777, + find_directory_callback, trash_volume); } -/* Remove the monitor from each of the directories in the list. */ static void -trash_file_monitor_remove (NautilusDirectory *directory, - gconstpointer client) +remove_trash_volume (TrashVolume *trash_volume) { - NautilusTrashDirectory *trash; - gpointer unique_client; - GList *p; + g_hash_table_remove (trash_volume->trash->details->volumes, + trash_volume->volume); - trash = NAUTILUS_TRASH_DIRECTORY (directory); - - /* Map the client to the value used by the earlier add call. */ - unique_client = g_hash_table_lookup - (trash->details->monitors, client); - if (unique_client == NULL) { - return; + if (trash_volume->handle != NULL) { + gnome_vfs_async_cancel (trash_volume->handle); } - g_hash_table_remove (trash->details->monitors, client); - - /* Call through to the real directory remove calls. */ - for (p = trash->details->directories; p != NULL; p = p->next) { - nautilus_directory_file_monitor_remove - (p->data, unique_client); + if (trash_volume->real_directory != NULL) { + nautilus_merged_directory_remove_real_directory + (NAUTILUS_MERGED_DIRECTORY (trash_volume->trash), + trash_volume->real_directory); } - - g_free (unique_client); + g_free (trash_volume); } -/* Return true only if all directories in the list do. */ -static gboolean -trash_are_all_files_seen (NautilusDirectory *directory) -{ - NautilusTrashDirectory *trash; - GList *p; - trash = NAUTILUS_TRASH_DIRECTORY (directory); +static void +remove_volume (NautilusTrashDirectory *trash, + NautilusVolume *volume) +{ + TrashVolume *trash_volume; - for (p = trash->details->directories; p != NULL; p = p->next) { - if (!nautilus_directory_are_all_files_seen (p->data)) { - return FALSE; - } + /* Quick out if don't already know about this volume. */ + trash_volume = g_hash_table_lookup (trash->details->volumes, + volume); + if (trash_volume != NULL) { + remove_trash_volume (trash_volume); } - return TRUE; } -/* Return true if any directory in the list does. */ static gboolean -trash_is_not_empty (NautilusDirectory *directory) +add_one_volume (const NautilusVolume *volume, + gpointer callback_data) { - NautilusTrashDirectory *trash; - GList *p; - - trash = NAUTILUS_TRASH_DIRECTORY (directory); - - for (p = trash->details->directories; p != NULL; p = p->next) { - if (nautilus_directory_is_not_empty (p->data)) { - return TRUE; - } - } - return FALSE; + /* The const is a kinda silly idea which we must cast away. */ + add_volume (NAUTILUS_TRASH_DIRECTORY (callback_data), + (NautilusVolume *) volume); + return FALSE; /* don't stop iterating */ } static void -nautilus_trash_directory_initialize_class (gpointer klass) +volume_mounted_callback (NautilusVolumeMonitor *monitor, + NautilusVolume *volume, + NautilusTrashDirectory *trash) { - GtkObjectClass *object_class; - NautilusDirectoryClass *directory_class; - - object_class = GTK_OBJECT_CLASS (klass); - directory_class = NAUTILUS_DIRECTORY_CLASS (klass); - - object_class->destroy = trash_destroy; - - directory_class->contains_file = trash_contains_file; - directory_class->call_when_ready = trash_call_when_ready; - directory_class->cancel_callback = trash_cancel_callback; - directory_class->file_monitor_add = trash_file_monitor_add; - directory_class->file_monitor_remove = trash_file_monitor_remove; - directory_class->are_all_files_seen = trash_are_all_files_seen; - directory_class->is_not_empty = trash_is_not_empty; + add_volume (trash, volume); } static void -forward_files_added_cover (NautilusDirectory *real_directory, - GList *files, +volume_unmounted_callback (NautilusVolumeMonitor *monitor, + NautilusVolume *volume, NautilusTrashDirectory *trash) { - nautilus_directory_emit_files_added (NAUTILUS_DIRECTORY (trash), files); -} - -static void -forward_files_changed_cover (NautilusDirectory *real_directory, - GList *files, - NautilusTrashDirectory *trash) -{ - nautilus_directory_emit_files_changed (NAUTILUS_DIRECTORY (trash), files); -} - -void -nautilus_trash_directory_add_real_directory (NautilusTrashDirectory *trash, - NautilusDirectory *real_directory) -{ - g_return_if_fail (NAUTILUS_IS_TRASH_DIRECTORY (trash)); - g_return_if_fail (NAUTILUS_IS_DIRECTORY (real_directory)); - g_return_if_fail (!NAUTILUS_IS_TRASH_DIRECTORY (real_directory)); - g_return_if_fail (g_list_find (trash->details->directories, real_directory) != NULL); - - /* Add to our list of directories. */ - nautilus_directory_ref (real_directory); - trash->details->directories = g_list_prepend - (trash->details->directories, real_directory); - - /* Connect signals. */ - gtk_signal_connect (GTK_OBJECT (real_directory), - "files_added", - forward_files_added_cover, - trash); - gtk_signal_connect (GTK_OBJECT (real_directory), - "files_changed", - forward_files_changed_cover, - trash); - /* FIXME: done_loading */ - - /* FIXME: Add to callbacks and monitors? */ + remove_volume (trash, volume); } static void -trash_callback_remove_directory_cover (gpointer key, - gpointer value, - gpointer callback_data) -{ - trash_callback_remove_directory - (value, NAUTILUS_DIRECTORY (callback_data)); -} - -void -nautilus_trash_directory_remove_real_directory (NautilusTrashDirectory *trash, - NautilusDirectory *real_directory) +nautilus_trash_directory_initialize (gpointer object, gpointer klass) { - g_return_if_fail (NAUTILUS_IS_TRASH_DIRECTORY (trash)); - g_return_if_fail (NAUTILUS_IS_DIRECTORY (real_directory)); + NautilusTrashDirectory *trash; + NautilusVolumeMonitor *volume_monitor; - /* Quietly do nothing if asked to remove something that's not there. */ - if (g_list_find (trash->details->directories, real_directory) == NULL) { - return; - } + trash = NAUTILUS_TRASH_DIRECTORY (object); - /* Remove this directory from callbacks and monitors. */ - g_hash_table_foreach (trash->details->callbacks, - trash_callback_remove_directory_cover, - real_directory); - /* FIXME: monitors. */ + trash->details = g_new0 (NautilusTrashDirectoryDetails, 1); + trash->details->volumes = g_hash_table_new + (g_direct_hash, g_direct_equal); - /* Disconnect all the signals. */ - gtk_signal_disconnect_by_data (GTK_OBJECT (real_directory), trash); + volume_monitor = nautilus_volume_monitor_get (); - /* Remove from our list of directories. */ - trash->details->directories = g_list_remove - (trash->details->directories, real_directory); - nautilus_directory_unref (real_directory); + gtk_signal_connect + (GTK_OBJECT (volume_monitor), "volume_mounted", + volume_mounted_callback, trash); + gtk_signal_connect + (GTK_OBJECT (volume_monitor), "volume_unmounted", + volume_unmounted_callback, trash); + nautilus_volume_monitor_each_mounted_volume + (volume_monitor, add_one_volume, trash); } static void -remove_all_real_directories (NautilusTrashDirectory *trash) +remove_trash_volume_cover (gpointer key, gpointer value, gpointer callback_data) { - while (trash->details->directories != NULL) { - nautilus_trash_directory_remove_real_directory - (trash, trash->details->directories->data); - } -} - -#if 0 + TrashVolume *trash_volume; - /* Find/create Trash directories */ -static void -fm_desktop_icon_view_discover_trash_callback (GnomeVFSAsyncHandle *handle, - GList *results, - gpointer callback_data) -{ -#if 0 - /* Debug code only for now. - * Bugzilla task 571 will use the resulting list to - * create new NautilusDirectory objects for Trash. - */ - GnomeVFSFindDirectoryResult *result; - GList *p; + g_assert (key != NULL); + g_assert (value != NULL); + g_assert (callback_data == NULL); - for (p = results; p != NULL; p = p->next) { - char *uri_text; + trash_volume = value; - result = p->data; - uri_text = ""; + g_assert (NAUTILUS_IS_TRASH_DIRECTORY (trash_volume->trash)); + g_assert (trash_volume->volume == key); - if (result->uri) { - uri_text = gnome_vfs_uri_to_string (result->uri, - GNOME_VFS_URI_HIDE_NONE); - } - - printf("trash dir %s, %s\n", uri_text, strerror (result->result)); - } -#endif + remove_trash_volume (trash_volume); } - nautilus_trash_monitor_async_get_trash_directories (fm_desktop_icon_view_discover_trash_callback, - desktop_icon_view); - -static gboolean -add_one_writable_device (const DeviceInfo *device, gpointer context) -{ - GList **uris = (GList **)context; - char *uri; - - if (device->type == DEVICE_EXT2 && !device->is_read_only) { - uri = nautilus_get_uri_from_local_path (device->mount_path); - *uris = g_list_prepend (*uris, gnome_vfs_uri_new (uri)); - g_free (uri); - } - return FALSE; -} - -static GList * -get_trashable_volume_uris (void) +static void +trash_destroy (GtkObject *object) { - GList *uris; + NautilusTrashDirectory *trash; - uris = NULL; + trash = NAUTILUS_TRASH_DIRECTORY (object); - nautilus_volume_monitor_each_mounted_device - (nautilus_volume_monitor_get (), - add_one_writable_device, &uris); + nautilus_g_hash_table_safe_for_each + (trash->details->volumes, + remove_trash_volume_cover, + NULL); + g_hash_table_destroy (trash->details->volumes); + g_free (trash->details); - return uris; + NAUTILUS_CALL_PARENT_CLASS (GTK_OBJECT_CLASS, destroy, (object)); } -/* FIXME: No way to cancel this. */ -void -nautilus_trash_monitor_async_get_trash_directories (GnomeVFSAsyncFindDirectoryCallback callback, - gpointer context) +static void +nautilus_trash_directory_initialize_class (gpointer klass) { - GList *uris; - GnomeVFSAsyncHandle *async_handle; + GtkObjectClass *object_class; + + object_class = GTK_OBJECT_CLASS (klass); - uris = get_trashable_volume_uris (); - gnome_vfs_async_find_directory - (&async_handle, uris, - GNOME_VFS_DIRECTORY_KIND_TRASH, TRUE, TRUE, 0777, - callback, context); - gnome_vfs_uri_list_free (uris); + object_class->destroy = trash_destroy; } -#endif diff --git a/libnautilus-private/nautilus-trash-directory.h b/libnautilus-private/nautilus-trash-directory.h index 9dec9f8a0..9af4cb6fd 100644 --- a/libnautilus-private/nautilus-trash-directory.h +++ b/libnautilus-private/nautilus-trash-directory.h @@ -1,7 +1,7 @@ /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- - nautilus-trash-directory.h: Subclass of NautilusDirectory to implement the - virtual trash directory. + nautilus-trash-directory.h: Subclass of NautilusDirectory to implement + the virtual trash directory. Copyright (C) 1999, 2000 Eazel, Inc. @@ -26,11 +26,7 @@ #ifndef NAUTILUS_TRASH_DIRECTORY_H #define NAUTILUS_TRASH_DIRECTORY_H -#include "nautilus-directory.h" - -/* Very little of this is trash-specific, so we could give it a new - * name some day. - */ +#include "nautilus-merged-directory.h" #define NAUTILUS_TYPE_TRASH_DIRECTORY \ (nautilus_trash_directory_get_type ()) @@ -46,18 +42,14 @@ typedef struct NautilusTrashDirectoryDetails NautilusTrashDirectoryDetails; typedef struct { - NautilusDirectory parent_slot; + NautilusMergedDirectory parent_slot; NautilusTrashDirectoryDetails *details; } NautilusTrashDirectory; typedef struct { - NautilusDirectoryClass parent_slot; + NautilusMergedDirectoryClass parent_slot; } NautilusTrashDirectoryClass; -GtkType nautilus_trash_directory_get_type (void); -void nautilus_trash_directory_add_real_directory (NautilusTrashDirectory *trash, - NautilusDirectory *real_directory); -void nautilus_trash_directory_remove_real_directory (NautilusTrashDirectory *trash, - NautilusDirectory *real_directory); +GtkType nautilus_trash_directory_get_type (void); #endif /* NAUTILUS_TRASH_DIRECTORY_H */ |