summaryrefslogtreecommitdiff
path: root/libnautilus-private
diff options
context:
space:
mode:
authorDarin Adler <darin@src.gnome.org>2000-08-22 02:11:45 +0000
committerDarin Adler <darin@src.gnome.org>2000-08-22 02:11:45 +0000
commit7295589544bf5b28024f25ab5783e0f8ec273502 (patch)
tree203998c60e5bc03a794a5162a8be544efe1bbeaf /libnautilus-private
parent509e16baa8b3854b9cfab973b7b01cb11652a0ed (diff)
downloadnautilus-7295589544bf5b28024f25ab5783e0f8ec273502.tar.gz
Finished task 571 (Make a Trash "virtual directory" with trash
from all volumes). Some loose ends are already reported in bugs 2146, 2243, and 2244. * libnautilus-extensions/Makefile.am: * libnautilus-extensions/nautilus-merged-directory.h: * libnautilus-extensions/nautilus-merged-directory.c: Moved all the guts of NautilusTrashDirectory that are solely about having a single directory that's a union of a bunch of real directories into a separate base class. Also finished the implementation, leaving only unimportant loose ends. * libnautilus-extensions/nautilus-trash-directory.h: * libnautilus-extensions/nautilus-trash-directory.c: (get_volume_vfs_uri_if_writable), (find_directory_callback), (add_volume), (remove_trash_volume), (remove_volume), (add_one_volume), (volume_mounted_callback), (volume_unmounted_callback), (nautilus_trash_directory_initialize), (remove_trash_volume_cover), (trash_destroy), (nautilus_trash_directory_initialize_class): Added the code to find the trash on all volumes. * libnautilus-extensions/nautilus-glib-extensions.h: * libnautilus-extensions/nautilus-glib-extensions.c: (flatten_hash_table_element), (nautilus_g_hash_table_safe_for_each): Added a new version of the hash table iterator that works even if the callback removes items from the hash table. * libnautilus-extensions/nautilus-scalable-font.c: (nautilus_scalable_font_largest_fitting_font_size): Added code to handle the case of an empty name; the old code worked with NULL, but not with "". * src/file-manager/fm-desktop-icon-view.c: (fm_desktop_icon_view_trash_state_changed_callback), (find_and_rename_trash_link), (create_or_rename_trash): * src/file-manager/nautilus-trash-monitor.c: (nautilus_trash_monitor_initialize): Changed to use the new "trash:" URL instead of locating one of the trash folders. * src/file-manager/fm-directory-view.h: * src/file-manager/fm-directory-view.c: (fm_directory_view_initialize_class), (fm_directory_all_selected_items_in_trash): * src/file-manager/fm-search-list-view.c: (fm_search_list_view_initialize_class): The "share_parent" optimization didn't work for the new trash. Instead of fixing it, I just removed it. * src/nautilus-window-manage-views.c: (compute_default_title), (nautilus_window_update_title): Made two changes to the default title: 1) Use "" instead of "Nautilus" when there's no title. We still use "Nautilus" in the window title, but not in the sidebar any more. 2) Use the scheme part of a URI if there's nothing after the colon. This works nicely for the trash. * libnautilus-extensions/nautilus-background-canvas-group.c: (nautilus_background_canvas_group_render): Removed some unneeded code and the FIXME that goes with it. * libnautilus-extensions/nautilus-directory.c: (nautilus_directory_is_not_empty): Removed an overzealous assert.
Diffstat (limited to 'libnautilus-private')
-rw-r--r--libnautilus-private/Makefile.am2
-rw-r--r--libnautilus-private/nautilus-background-canvas-group.c3
-rw-r--r--libnautilus-private/nautilus-directory.c1
-rw-r--r--libnautilus-private/nautilus-glib-extensions.c42
-rw-r--r--libnautilus-private/nautilus-glib-extensions.h87
-rw-r--r--libnautilus-private/nautilus-merged-directory.c553
-rw-r--r--libnautilus-private/nautilus-merged-directory.h60
-rw-r--r--libnautilus-private/nautilus-scalable-font.c2
-rw-r--r--libnautilus-private/nautilus-trash-directory.c606
-rw-r--r--libnautilus-private/nautilus-trash-directory.h20
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 */