summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarin Adler <darin@src.gnome.org>2001-01-18 19:26:03 +0000
committerDarin Adler <darin@src.gnome.org>2001-01-18 19:26:03 +0000
commite82bab8c493c3d173622c18e5df07e3f36d982ea (patch)
tree1c763ef60fff7ef1197243c4f19ca0d332af35df
parentaee3945efe11c38873effaa5aff0121163cd030e (diff)
downloadnautilus-e82bab8c493c3d173622c18e5df07e3f36d982ea.tar.gz
reviewed by: John Sullivan <sullivan@eazel.com>
Fixed bug 2147 (NautilusFile for trash needs non-empty values for more properties), bug 5652 (MIME type field appears but shouldn't in properties window for Trash), and bug 4620 (trash sidebar should show number of items). * libnautilus-extensions/nautilus-file.h: * libnautilus-extensions/nautilus-file-private.h: * libnautilus-extensions/nautilus-file.c: (nautilus_file_new_from_relative_uri): Create trash file subclass when appropriate. (nautilus_file_info_missing): Rename so it can be used in other source files. (nautilus_file_get_date): New method that returns numeric dates. (nautilus_file_get_date_as_string): Change to call nautilus_file_get_date to get the numeric date. (nautilus_file_get_file_type): Turn into a method. * libnautilus-extensions/nautilus-merged-directory.h: * libnautilus-extensions/nautilus-merged-directory.c: (merged_call_when_ready): Rolled in the old merged_callback_connect_directory function. (merged_contains_file): Moved down to a more appropriate part of the source file. (nautilus_merged_directory_get_real_directories): New public function for use by trash. * libnautilus-extensions/nautilus-trash-file.c: (trash_callback_hash), (trash_callback_equal), (trash_callback_destroy), (trash_callback_check_done), (trash_callback_remove_file), (ready_callback), (real_file_changed_callback), (monitor_add_file), (add_real_file), (trash_callback_remove_file_cover), (monitor_remove_file), (remove_real_file), (add_real_file_given_directory), (add_directory_callback), (remove_directory_callback), (trash_file_call_when_ready), (trash_file_cancel_call_when_ready), (trash_file_check_if_ready), (trash_file_monitor_add), (trash_file_monitor_remove), (trash_file_get_file_type), (trash_file_get_item_count), (trash_file_get_deep_counts), (trash_file_get_date), (remove_all_real_files), (nautilus_trash_file_initialize), (trash_destroy), (nautilus_trash_file_initialize_class): New code. First implementation of getting some attributes for the merged trash. Gets list of directories from the NautilusTrashDirectory object. The code in here is similar to the NautilusMergedDirectory class and at some point perhaps we can make the two share more. * libnautilus-extensions/nautilus-vfs-file.c: (vfs_file_get_file_type), (vfs_file_get_date), (nautilus_vfs_file_initialize_class): Implement the two new methods for the standard vfs case. Fixed various things that affect the properties window for the trash that showed up while I was testing the above work: * libnautilus-extensions/nautilus-icon-factory.c: (nautilus_icon_factory_get_icon_name_for_regular_file), (nautilus_icon_factory_get_icon_name_for_file): Move trash special case out so it doesn't matter what type the trash seems to be. The old code relied on trash not being a directory. * src/file-manager/fm-properties-window.c: (create_properties_window), (create_properties_window_callback), (cancel_create_properties_window_callback), (directory_view_destroyed_callback), (remove_pending_file): Rework code to fix problems where the timed wait or the signal handler wasn't properly cleaned up. Fixed remaining bit of bug 5631 (Tear-offs of right-click menus don't work.): * src/file-manager/nautilus-desktop-icon-view-ui.xml: Mark Disks right-click submenu so it won't get a tear-off item. Fixed bug 5650 (nautilus --quit fails to return to prompt sometimes): * src/nautilus-application.c: (nautilus_application_startup): Add special case so "nautilus --quit" doesn't hang waiting for a response from the (now quit) "server" instance of Nautilus. * src/nautilus-shell-interface.idl: Had to make the quit call no longer be "oneway" to get it to work right, otherwise the quit message could be lost when the sending application exited too fast. Fix bug 5675 (Nitpicks in new "could not be moved to new special location" dialog): * libnautilus-extensions/nautilus-file-operations.c: (handle_transfer_overwrite): Updated message wording as Eli (and Vera) suggest. Other changes: * libnautilus-extensions/nautilus-view-identifier.c: (get_lang_list): Fix comment and a small storage leak in the case where lang_with_locale is non-NULL but empty. * po/POTFILES.ignore: Obsolete file, no longer used. * src/file-manager/fm-desktop-icon-view.c: (update_home_link_and_delete_copies): Update comment to help translators understand better. * libnautilus-extensions/nautilus-directory-async.c: (directory_load_callback): Added a new assertion that could help in future gnome-vfs debugging. * libnautilus/nautilus-view-component.idl: Removed long-ago-fixed FIXME comment. * src/nautilus-window-manage-views.c: Tweak spacing.
-rw-r--r--ChangeLog118
-rw-r--r--libnautilus-extensions/nautilus-directory-async.c1
-rw-r--r--libnautilus-extensions/nautilus-file-operations.c14
-rw-r--r--libnautilus-extensions/nautilus-file-private.h43
-rw-r--r--libnautilus-extensions/nautilus-file.c142
-rw-r--r--libnautilus-extensions/nautilus-file.h14
-rw-r--r--libnautilus-extensions/nautilus-icon-factory.c15
-rw-r--r--libnautilus-extensions/nautilus-merged-directory.c100
-rw-r--r--libnautilus-extensions/nautilus-merged-directory.h1
-rw-r--r--libnautilus-extensions/nautilus-trash-file.c571
-rw-r--r--libnautilus-extensions/nautilus-vfs-file.c72
-rw-r--r--libnautilus-extensions/nautilus-view-identifier.c7
-rw-r--r--libnautilus-private/nautilus-directory-async.c1
-rw-r--r--libnautilus-private/nautilus-file-operations.c14
-rw-r--r--libnautilus-private/nautilus-file-private.h43
-rw-r--r--libnautilus-private/nautilus-file.c142
-rw-r--r--libnautilus-private/nautilus-file.h14
-rw-r--r--libnautilus-private/nautilus-icon-factory.c15
-rw-r--r--libnautilus-private/nautilus-merged-directory.c100
-rw-r--r--libnautilus-private/nautilus-merged-directory.h1
-rw-r--r--libnautilus-private/nautilus-trash-file.c571
-rw-r--r--libnautilus-private/nautilus-vfs-file.c72
-rw-r--r--libnautilus-private/nautilus-view-identifier.c7
-rw-r--r--libnautilus/nautilus-view-component.idl5
-rw-r--r--po/POTFILES.ignore1
-rw-r--r--src/file-manager/fm-desktop-icon-view.c5
-rw-r--r--src/file-manager/fm-properties-window.c121
-rw-r--r--src/file-manager/nautilus-desktop-icon-view-ui.xml2
-rw-r--r--src/nautilus-application.c9
-rw-r--r--src/nautilus-shell-interface.idl12
-rw-r--r--src/nautilus-window-manage-views.c1
31 files changed, 1799 insertions, 435 deletions
diff --git a/ChangeLog b/ChangeLog
index e5dc34653..663ca4a9b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,120 @@
+2001-01-18 Darin Adler <darin@eazel.com>
+
+ reviewed by: John Sullivan <sullivan@eazel.com>
+
+ Fixed bug 2147 (NautilusFile for trash needs non-empty values for
+ more properties), bug 5652 (MIME type field appears but shouldn't
+ in properties window for Trash), and bug 4620 (trash sidebar
+ should show number of items).
+
+ * libnautilus-extensions/nautilus-file.h:
+ * libnautilus-extensions/nautilus-file-private.h:
+ * libnautilus-extensions/nautilus-file.c:
+ (nautilus_file_new_from_relative_uri): Create trash file subclass
+ when appropriate.
+ (nautilus_file_info_missing): Rename so it can be used in other
+ source files.
+ (nautilus_file_get_date): New method that returns numeric dates.
+ (nautilus_file_get_date_as_string): Change to call
+ nautilus_file_get_date to get the numeric date.
+ (nautilus_file_get_file_type): Turn into a method.
+
+ * libnautilus-extensions/nautilus-merged-directory.h:
+ * libnautilus-extensions/nautilus-merged-directory.c:
+ (merged_call_when_ready): Rolled in the old
+ merged_callback_connect_directory function.
+ (merged_contains_file): Moved down to a more appropriate part of
+ the source file.
+ (nautilus_merged_directory_get_real_directories): New public
+ function for use by trash.
+
+ * libnautilus-extensions/nautilus-trash-file.c:
+ (trash_callback_hash), (trash_callback_equal),
+ (trash_callback_destroy), (trash_callback_check_done),
+ (trash_callback_remove_file), (ready_callback),
+ (real_file_changed_callback), (monitor_add_file), (add_real_file),
+ (trash_callback_remove_file_cover), (monitor_remove_file),
+ (remove_real_file), (add_real_file_given_directory),
+ (add_directory_callback), (remove_directory_callback),
+ (trash_file_call_when_ready), (trash_file_cancel_call_when_ready),
+ (trash_file_check_if_ready), (trash_file_monitor_add),
+ (trash_file_monitor_remove), (trash_file_get_file_type),
+ (trash_file_get_item_count), (trash_file_get_deep_counts),
+ (trash_file_get_date), (remove_all_real_files),
+ (nautilus_trash_file_initialize), (trash_destroy),
+ (nautilus_trash_file_initialize_class):
+ New code. First implementation of getting some attributes for the
+ merged trash. Gets list of directories from the
+ NautilusTrashDirectory object. The code in here is similar to the
+ NautilusMergedDirectory class and at some point perhaps we can
+ make the two share more.
+
+ * libnautilus-extensions/nautilus-vfs-file.c:
+ (vfs_file_get_file_type), (vfs_file_get_date),
+ (nautilus_vfs_file_initialize_class): Implement the two new
+ methods for the standard vfs case.
+
+ Fixed various things that affect the properties window for the
+ trash that showed up while I was testing the above work:
+
+ * libnautilus-extensions/nautilus-icon-factory.c:
+ (nautilus_icon_factory_get_icon_name_for_regular_file),
+ (nautilus_icon_factory_get_icon_name_for_file): Move trash special
+ case out so it doesn't matter what type the trash seems to be. The
+ old code relied on trash not being a directory.
+
+ * src/file-manager/fm-properties-window.c:
+ (create_properties_window), (create_properties_window_callback),
+ (cancel_create_properties_window_callback),
+ (directory_view_destroyed_callback), (remove_pending_file): Rework
+ code to fix problems where the timed wait or the signal handler
+ wasn't properly cleaned up.
+
+ Fixed remaining bit of bug 5631 (Tear-offs of right-click menus
+ don't work.):
+
+ * src/file-manager/nautilus-desktop-icon-view-ui.xml: Mark Disks
+ right-click submenu so it won't get a tear-off item.
+
+ Fixed bug 5650 (nautilus --quit fails to return to prompt
+ sometimes):
+
+ * src/nautilus-application.c: (nautilus_application_startup): Add
+ special case so "nautilus --quit" doesn't hang waiting for a
+ response from the (now quit) "server" instance of Nautilus.
+ * src/nautilus-shell-interface.idl: Had to make the quit call no
+ longer be "oneway" to get it to work right, otherwise the quit
+ message could be lost when the sending application exited too
+ fast.
+
+ Fix bug 5675 (Nitpicks in new "could not be moved to new special
+ location" dialog):
+
+ * libnautilus-extensions/nautilus-file-operations.c:
+ (handle_transfer_overwrite): Updated message wording as Eli (and
+ Vera) suggest.
+
+ Other changes:
+
+ * libnautilus-extensions/nautilus-view-identifier.c:
+ (get_lang_list): Fix comment and a small storage leak in the case
+ where lang_with_locale is non-NULL but empty.
+
+ * po/POTFILES.ignore: Obsolete file, no longer used.
+
+ * src/file-manager/fm-desktop-icon-view.c:
+ (update_home_link_and_delete_copies): Update comment to help
+ translators understand better.
+
+ * libnautilus-extensions/nautilus-directory-async.c:
+ (directory_load_callback): Added a new assertion that could help
+ in future gnome-vfs debugging.
+
+ * libnautilus/nautilus-view-component.idl: Removed long-ago-fixed
+ FIXME comment.
+
+ * src/nautilus-window-manage-views.c: Tweak spacing.
+
2001-01-18 John Sullivan <sullivan@eazel.com>
reviewed by: Darin Adler <darin@eazel.com>
@@ -585,7 +702,6 @@
(nautilus_list_get_drop_action):
Tiny tweak.
->>>>>>> 1.3384
2001-01-16 Michael Engber <engber@eazel.com>
* libnautilus-extensions/nautilus-directory-background.c:
diff --git a/libnautilus-extensions/nautilus-directory-async.c b/libnautilus-extensions/nautilus-directory-async.c
index b065b89b0..d0dc48832 100644
--- a/libnautilus-extensions/nautilus-directory-async.c
+++ b/libnautilus-extensions/nautilus-directory-async.c
@@ -1414,6 +1414,7 @@ directory_load_callback (GnomeVFSAsyncHandle *handle,
directory = NAUTILUS_DIRECTORY (callback_data);
+ g_assert (directory->details->directory_load_in_progress != NULL);
g_assert (directory->details->directory_load_in_progress == handle);
/* Move items from the list onto our pending queue.
diff --git a/libnautilus-extensions/nautilus-file-operations.c b/libnautilus-extensions/nautilus-file-operations.c
index 03ce35c59..f58ee5f93 100644
--- a/libnautilus-extensions/nautilus-file-operations.c
+++ b/libnautilus-extensions/nautilus-file-operations.c
@@ -1000,22 +1000,22 @@ handle_transfer_overwrite (const GnomeVFSXferProgressInfo *progress_info,
/* Handle special case files such as Trash, mount links and home directory */
if (is_special_link (progress_info->target_name)) {
- formatted_name = extract_and_ellipsize_file_name_for_dialog (progress_info->target_name);
+ formatted_name = extract_and_ellipsize_file_name_for_dialog
+ (progress_info->target_name);
if (transfer_info->kind == TRANSFER_MOVE) {
text = g_strdup_printf (_("\"%s\" could not be moved to the new location, "
- "because the name is already used for a special item that "
- "cannot be removed or replaced. "
+ "because its name is already used for a special item that "
+ "cannot be removed or replaced.\n\n"
"If you still want to move \"%s\", rename it and try again."),
formatted_name, formatted_name);
} else {
text = g_strdup_printf (_("\"%s\" could not be copied to the new location, "
- "because the name is already used for a special item that "
- "cannot be removed or replaced. "
+ "because its name is already used for a special item that "
+ "cannot be removed or replaced.\n\n"
"If you still want to copy \"%s\", rename it and try again."),
formatted_name, formatted_name);
-
- };
+ }
nautilus_simple_dialog (parent_for_error_dialog (transfer_info), TRUE, text,
_("Unable to replace file."), _("OK"), NULL, NULL);
diff --git a/libnautilus-extensions/nautilus-file-private.h b/libnautilus-extensions/nautilus-file-private.h
index de0a113ab..ed981017f 100644
--- a/libnautilus-extensions/nautilus-file-private.h
+++ b/libnautilus-extensions/nautilus-file-private.h
@@ -99,36 +99,41 @@ struct NautilusFileDetails
nautilus_boolean_bit activation_uri_is_up_to_date : 1;
};
-NautilusFile *nautilus_file_new_from_info (NautilusDirectory *directory,
- GnomeVFSFileInfo *info);
-NautilusFile *nautilus_file_get_existing (const char *uri);
-void nautilus_file_emit_changed (NautilusFile *file);
-void nautilus_file_mark_gone (NautilusFile *file);
-char * nautilus_extract_top_left_text (const char *text,
- int length);
-gboolean nautilus_file_contains_text (NautilusFile *file);
-void nautilus_file_set_directory (NautilusFile *file,
- NautilusDirectory *directory);
+NautilusFile *nautilus_file_new_from_info (NautilusDirectory *directory,
+ GnomeVFSFileInfo *info);
+NautilusFile *nautilus_file_get_existing (const char *uri);
+void nautilus_file_emit_changed (NautilusFile *file);
+void nautilus_file_mark_gone (NautilusFile *file);
+gboolean nautilus_file_info_missing (NautilusFile *file,
+ GnomeVFSFileInfoFields needed_mask);
+char * nautilus_extract_top_left_text (const char *text,
+ int length);
+gboolean nautilus_file_contains_text (NautilusFile *file);
+void nautilus_file_set_directory (NautilusFile *file,
+ NautilusDirectory *directory);
+gboolean nautilus_file_get_date (NautilusFile *file,
+ NautilusDateType date_type,
+ time_t *date);
/* Compare file's state with a fresh file info struct, return FALSE if
* no change, update file and return TRUE if the file info contains
* new state. */
-gboolean nautilus_file_update_info (NautilusFile *file,
- GnomeVFSFileInfo *info);
-gboolean nautilus_file_update_name (NautilusFile *file,
- const char *name);
+gboolean nautilus_file_update_info (NautilusFile *file,
+ GnomeVFSFileInfo *info);
+gboolean nautilus_file_update_name (NautilusFile *file,
+ const char *name);
/* Return true if the top lefts of files in this directory should be
* fetched, according to the preference settings.
*/
-gboolean nautilus_file_should_get_top_left_text (NautilusFile *file);
+gboolean nautilus_file_should_get_top_left_text (NautilusFile *file);
/* Mark specified attributes for this file out of date without canceling current
* I/O or kicking off new I/O.
*/
-void nautilus_file_invalidate_attributes_internal (NautilusFile *file,
- GList *file_attributes);
+void nautilus_file_invalidate_attributes_internal (NautilusFile *file,
+ GList *file_attributes);
/* Recognizing special file names. */
-gboolean nautilus_file_name_matches_hidden_pattern (const char *name_or_relative_uri);
-gboolean nautilus_file_name_matches_backup_pattern (const char *name_or_relative_uri);
+gboolean nautilus_file_name_matches_hidden_pattern (const char *name_or_relative_uri);
+gboolean nautilus_file_name_matches_backup_pattern (const char *name_or_relative_uri);
diff --git a/libnautilus-extensions/nautilus-file.c b/libnautilus-extensions/nautilus-file.c
index d9cd0c162..d4ea4a908 100644
--- a/libnautilus-extensions/nautilus-file.c
+++ b/libnautilus-extensions/nautilus-file.c
@@ -37,6 +37,7 @@
#include "nautilus-lib-self-check-functions.h"
#include "nautilus-link.h"
#include "nautilus-string.h"
+#include "nautilus-trash-directory.h"
#include "nautilus-trash-file.h"
#include "nautilus-vfs-file.h"
#include <ctype.h>
@@ -69,13 +70,6 @@ extern void eazel_dump_stack_trace (const char *print_prefix,
/* Name to use to tag metadata for the directory itself. */
#define FILE_NAME_FOR_DIRECTORY_METADATA "."
-typedef enum {
- NAUTILUS_DATE_TYPE_MODIFIED,
- NAUTILUS_DATE_TYPE_CHANGED,
- NAUTILUS_DATE_TYPE_ACCESSED,
- NAUTILUS_DATE_TYPE_PERMISSIONS_CHANGED
-} NautilusDateType;
-
typedef struct {
NautilusFile *file;
GnomeVFSAsyncHandle *handle;
@@ -133,7 +127,8 @@ nautilus_file_initialize (NautilusFile *file)
static NautilusFile *
nautilus_file_new_from_relative_uri (NautilusDirectory *directory,
- const char *relative_uri)
+ const char *relative_uri,
+ gboolean self_owned)
{
NautilusFile *file;
@@ -141,7 +136,11 @@ nautilus_file_new_from_relative_uri (NautilusDirectory *directory,
g_return_val_if_fail (relative_uri != NULL, NULL);
g_return_val_if_fail (relative_uri[0] != '\0', NULL);
- file = NAUTILUS_FILE (gtk_object_new (NAUTILUS_TYPE_VFS_FILE, NULL));
+ if (self_owned && NAUTILUS_IS_TRASH_DIRECTORY (directory)) {
+ file = NAUTILUS_FILE (gtk_object_new (NAUTILUS_TYPE_TRASH_FILE, NULL));
+ } else {
+ file = NAUTILUS_FILE (gtk_object_new (NAUTILUS_TYPE_VFS_FILE, NULL));
+ }
gtk_object_ref (GTK_OBJECT (file));
gtk_object_sink (GTK_OBJECT (file));
@@ -158,8 +157,8 @@ nautilus_file_new_from_relative_uri (NautilusDirectory *directory,
return file;
}
-static gboolean
-info_missing (NautilusFile *file, GnomeVFSFileInfoFields needed_mask)
+gboolean
+nautilus_file_info_missing (NautilusFile *file, GnomeVFSFileInfoFields needed_mask)
{
GnomeVFSFileInfo *info;
@@ -185,7 +184,7 @@ modify_link_hash_table (NautilusFile *file,
GList *list;
/* Check if there is a symlink name. If none, we are OK. */
- if (info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_SYMLINK_NAME)) {
+ if (nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_SYMLINK_NAME)) {
return;
}
symlink_name = file->details->info->symlink_name;
@@ -356,7 +355,7 @@ nautilus_file_get_internal (const char *uri, gboolean create)
if (file != NULL) {
nautilus_file_ref (file);
} else if (create) {
- file = nautilus_file_new_from_relative_uri (directory, relative_uri);
+ file = nautilus_file_new_from_relative_uri (directory, relative_uri, self_owned);
if (self_owned) {
g_assert (directory->details->as_file == NULL);
directory->details->as_file = file;
@@ -1077,7 +1076,7 @@ update_link (NautilusFile *link_file, NautilusFile *target_file)
{
g_assert (NAUTILUS_IS_FILE (link_file));
g_assert (NAUTILUS_IS_FILE (target_file));
- g_assert (!info_missing (link_file, GNOME_VFS_FILE_INFO_FIELDS_SYMLINK_NAME));
+ g_assert (!nautilus_file_info_missing (link_file, GNOME_VFS_FILE_INFO_FIELDS_SYMLINK_NAME));
/* FIXME bugzilla.eazel.com 2044: If we don't put any code
* here then the hash table is a waste of time.
@@ -2159,7 +2158,29 @@ nautilus_file_get_uri_scheme (NautilusFile *file)
colon - file->details->directory->details->uri);
}
+gboolean
+nautilus_file_get_date (NautilusFile *file,
+ NautilusDateType date_type,
+ time_t *date)
+{
+ if (date != NULL) {
+ *date = 0;
+ }
+
+ g_return_val_if_fail (date_type == NAUTILUS_DATE_TYPE_CHANGED
+ || date_type == NAUTILUS_DATE_TYPE_ACCESSED
+ || date_type == NAUTILUS_DATE_TYPE_MODIFIED
+ || date_type == NAUTILUS_DATE_TYPE_PERMISSIONS_CHANGED, FALSE);
+
+ if (file == NULL) {
+ return FALSE;
+ }
+ g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
+
+ return NAUTILUS_CALL_VIRTUAL (NAUTILUS_FILE_CLASS, file,
+ get_date, (file, date_type, date));
+}
/**
* nautilus_file_get_date_as_string:
@@ -2173,61 +2194,19 @@ nautilus_file_get_uri_scheme (NautilusFile *file)
**/
static char *
nautilus_file_get_date_as_string (NautilusFile *file, NautilusDateType date_type)
-{
- struct tm *file_time = NULL;
+{
+ time_t file_time_raw;
+ struct tm *file_time;
const char *format;
GDate *today;
GDate *file_date;
guint32 file_date_age;
- g_return_val_if_fail (date_type == NAUTILUS_DATE_TYPE_CHANGED
- || date_type == NAUTILUS_DATE_TYPE_ACCESSED
- || date_type == NAUTILUS_DATE_TYPE_MODIFIED
- || date_type == NAUTILUS_DATE_TYPE_PERMISSIONS_CHANGED, NULL);
-
- switch (date_type) {
- case NAUTILUS_DATE_TYPE_CHANGED:
- /* Before we have info on a file, the date is unknown. */
- if (info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_CTIME)) {
- return NULL;
- }
- file_time = localtime (&file->details->info->ctime);
- break;
- case NAUTILUS_DATE_TYPE_ACCESSED:
- /* Before we have info on a file, the date is unknown. */
- if (info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_ATIME)) {
- return NULL;
- }
- file_time = localtime (&file->details->info->atime);
- break;
- case NAUTILUS_DATE_TYPE_MODIFIED:
- /* Before we have info on a file, the date is unknown. */
- if (info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_MTIME)) {
- return NULL;
- }
- file_time = localtime (&file->details->info->mtime);
- break;
- case NAUTILUS_DATE_TYPE_PERMISSIONS_CHANGED:
- /* Before we have info on a file, the date is unknown. */
- if (info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_MTIME) ||
- info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_CTIME)) {
- return NULL;
- }
- /* mtime is when the contents changed; ctime is when the
- * contents or the permissions (inc. owner/group) changed.
- * So we can only know when the permissions changed if mtime
- * and ctime are different.
- */
- if (file->details->info->mtime == file->details->info->ctime) {
- return NULL;
- }
-
- file_time = localtime (&file->details->info->ctime);
- break;
- default:
- g_assert_not_reached ();
+ if (!nautilus_file_get_date (file, date_type, &file_time_raw)) {
+ return NULL;
}
+ file_time = localtime (&file_time_raw);
file_date = nautilus_g_date_new_tm (file_time);
today = g_date_new ();
@@ -2298,13 +2277,12 @@ nautilus_file_get_directory_item_count (NautilusFile *file,
guint *count,
gboolean *count_unreadable)
{
+ if (count != NULL) {
+ *count = 0;
+ }
if (count_unreadable != NULL) {
- *count_unreadable = 0;
+ *count_unreadable = FALSE;
}
-
- g_return_val_if_fail (count != NULL, FALSE);
-
- *count = 0;
g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
@@ -2414,7 +2392,7 @@ GnomeVFSFileSize
nautilus_file_get_size (NautilusFile *file)
{
/* Before we have info on the file, we don't know the size. */
- return info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_SIZE)
+ return nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_SIZE)
? 0 : file->details->info->size;
}
@@ -2431,7 +2409,7 @@ nautilus_file_get_size (NautilusFile *file)
gboolean
nautilus_file_can_get_permissions (NautilusFile *file)
{
- return !info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS);
+ return !nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS);
}
/**
@@ -2720,7 +2698,7 @@ nautilus_file_can_get_owner (NautilusFile *file)
* Can we trust the uid in the file info? Might
* there be garbage there? What will it do for non-local files?
*/
- return !info_missing (file, 0 /* FIXME bugzilla.eazel.com 644: GNOME_VFS_FILE_INFO_FIELDS_UID */);
+ return !nautilus_file_info_missing (file, 0 /* FIXME bugzilla.eazel.com 644: GNOME_VFS_FILE_INFO_FIELDS_UID */);
}
/**
@@ -2935,7 +2913,7 @@ nautilus_file_can_get_group (NautilusFile *file)
* Can we trust the gid in the file info? Might
* there be garbage there? What will it do for non-local files?
*/
- return !info_missing (file, 0 /* FIXME bugzilla.eazel.com 644: GNOME_VFS_FILE_INFO_FIELDS_GID */);
+ return !nautilus_file_info_missing (file, 0 /* FIXME bugzilla.eazel.com 644: GNOME_VFS_FILE_INFO_FIELDS_GID */);
}
/**
@@ -2955,7 +2933,7 @@ nautilus_file_get_group_name (NautilusFile *file)
struct group *group_info;
/* Before we have info on a file, the owner is unknown. */
- if (info_missing (file, 0 /* FIXME bugzilla.eazel.com 644: GNOME_VFS_FILE_INFO_FIELDS_GID */)) {
+ if (nautilus_file_info_missing (file, 0 /* FIXME bugzilla.eazel.com 644: GNOME_VFS_FILE_INFO_FIELDS_GID */)) {
return NULL;
}
@@ -3284,7 +3262,7 @@ nautilus_file_get_owner_as_string (NautilusFile *file, gboolean include_real_nam
* Can we trust the uid in the file info? Might
* there be garbage there? What will it do for non-local files?
*/
- if (info_missing (file, 0 /* FIXME bugzilla.eazel.com 644: GNOME_VFS_FILE_INFO_FIELDS_UID */)) {
+ if (nautilus_file_info_missing (file, 0 /* FIXME bugzilla.eazel.com 644: GNOME_VFS_FILE_INFO_FIELDS_UID */)) {
return NULL;
}
@@ -3357,7 +3335,7 @@ nautilus_file_get_size_as_string (NautilusFile *file)
return format_item_count_for_display (item_count, TRUE, TRUE);
}
- if (info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_SIZE)) {
+ if (nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_SIZE)) {
return NULL;
}
return gnome_vfs_format_file_size_for_display (file->details->info->size);
@@ -3750,8 +3728,10 @@ nautilus_file_get_type_as_string (NautilusFile *file)
GnomeVFSFileType
nautilus_file_get_file_type (NautilusFile *file)
{
- return info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_TYPE)
- ? GNOME_VFS_FILE_TYPE_UNKNOWN : file->details->info->type;
+ if (file == NULL) {
+ return GNOME_VFS_FILE_TYPE_UNKNOWN;
+ }
+ return NAUTILUS_CALL_VIRTUAL (NAUTILUS_FILE_CLASS, file, get_file_type, (file));
}
/**
@@ -3908,7 +3888,7 @@ nautilus_file_set_keywords (NautilusFile *file, GList *keywords)
gboolean
nautilus_file_is_symbolic_link (NautilusFile *file)
{
- return info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_FLAGS)
+ return nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_FLAGS)
? FALSE : (file->details->info->flags & GNOME_VFS_FILE_FLAGS_SYMLINK);
}
@@ -3948,7 +3928,7 @@ nautilus_file_get_symbolic_link_target_path (NautilusFile *file)
{
g_return_val_if_fail (nautilus_file_is_symbolic_link (file), NULL);
- return info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_SYMLINK_NAME)
+ return nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_SYMLINK_NAME)
? NULL
: g_strdup (file->details->info->symlink_name);
}
@@ -3980,12 +3960,6 @@ nautilus_file_is_nautilus_link (NautilusFile *file)
gboolean
nautilus_file_is_directory (NautilusFile *file)
{
- if (file == NULL) {
- return FALSE;
- }
-
- g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
-
return nautilus_file_get_file_type (file) == GNOME_VFS_FILE_TYPE_DIRECTORY;
}
diff --git a/libnautilus-extensions/nautilus-file.h b/libnautilus-extensions/nautilus-file.h
index 2f0f26f74..9c7abe03f 100644
--- a/libnautilus-extensions/nautilus-file.h
+++ b/libnautilus-extensions/nautilus-file.h
@@ -288,6 +288,16 @@ struct NautilusFile {
NautilusFileDetails *details;
};
+/* This is actually a "protected" type, but it must be here so we can
+ * compile the get_date function pointer declaration below.
+ */
+typedef enum {
+ NAUTILUS_DATE_TYPE_MODIFIED,
+ NAUTILUS_DATE_TYPE_CHANGED,
+ NAUTILUS_DATE_TYPE_ACCESSED,
+ NAUTILUS_DATE_TYPE_PERMISSIONS_CHANGED
+} NautilusDateType;
+
typedef struct {
GtkObjectClass parent_slot;
@@ -309,6 +319,7 @@ typedef struct {
gpointer callback_data);
gboolean (* check_if_ready) (NautilusFile *file,
GList *attributes);
+ GnomeVFSFileType (* get_file_type) (NautilusFile *file);
gboolean (* get_item_count) (NautilusFile *file,
guint *count,
gboolean *count_unreadable);
@@ -317,6 +328,9 @@ typedef struct {
guint *file_count,
guint *unreadable_directory_count,
GnomeVFSFileSize *total_size);
+ gboolean (* get_date) (NautilusFile *file,
+ NautilusDateType type,
+ time_t *date);
} NautilusFileClass;
#endif /* NAUTILUS_FILE_H */
diff --git a/libnautilus-extensions/nautilus-icon-factory.c b/libnautilus-extensions/nautilus-icon-factory.c
index ed324c8c1..25cca9aaa 100644
--- a/libnautilus-extensions/nautilus-icon-factory.c
+++ b/libnautilus-extensions/nautilus-icon-factory.c
@@ -766,9 +766,6 @@ nautilus_icon_factory_get_icon_name_for_regular_file (NautilusFile *file)
icon_name = ICON_NAME_WEB;
} else if (nautilus_istr_has_prefix (uri, "eazel-install:")) {
icon_name = ICON_NAME_INSTALL;
- } else if (strcmp (uri, NAUTILUS_TRASH_URI) == 0) {
- icon_name = nautilus_trash_monitor_is_empty ()
- ? ICON_NAME_TRASH_EMPTY : ICON_NAME_TRASH_NOT_EMPTY;
} else {
if (nautilus_file_is_executable (file)
&& nautilus_strcasecmp (mime_type, "text/plain") != 0) {
@@ -798,7 +795,7 @@ nautilus_icon_factory_get_icon_name_for_directory (NautilusFile *file)
} else {
icon_name = ICON_NAME_DIRECTORY;
}
-
+
g_free (mime_type);
return icon_name;
@@ -809,6 +806,16 @@ nautilus_icon_factory_get_icon_name_for_directory (NautilusFile *file)
static const char *
nautilus_icon_factory_get_icon_name_for_file (NautilusFile *file)
{
+ char *uri;
+
+ uri = nautilus_file_get_uri (file);
+ if (strcmp (uri, NAUTILUS_TRASH_URI) == 0) {
+ g_free (uri);
+ return nautilus_trash_monitor_is_empty ()
+ ? ICON_NAME_TRASH_EMPTY : ICON_NAME_TRASH_NOT_EMPTY;
+ }
+ g_free (uri);
+
/* Get an icon name based on the file's type. */
switch (nautilus_file_get_file_type (file)) {
case GNOME_VFS_FILE_TYPE_DIRECTORY:
diff --git a/libnautilus-extensions/nautilus-merged-directory.c b/libnautilus-extensions/nautilus-merged-directory.c
index 2bea0815a..4d8bd3448 100644
--- a/libnautilus-extensions/nautilus-merged-directory.c
+++ b/libnautilus-extensions/nautilus-merged-directory.c
@@ -139,24 +139,6 @@ merged_callback_equal (gconstpointer merged_callback_as_pointer,
&& 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)
{
@@ -196,8 +178,6 @@ merged_callback_remove_directory (MergedCallback *merged_callback,
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);
}
@@ -220,18 +200,7 @@ directory_ready_callback (NautilusDirectory *directory,
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,
- directory_ready_callback, merged_callback);
+ merged_callback_remove_directory (merged_callback, directory);
}
static void
@@ -242,7 +211,7 @@ merged_call_when_ready (NautilusDirectory *directory,
{
NautilusMergedDirectory *merged;
MergedCallback search_key, *merged_callback;
- GList *p;
+ GList *node;
merged = NAUTILUS_MERGED_DIRECTORY (directory);
@@ -260,9 +229,9 @@ merged_call_when_ready (NautilusDirectory *directory,
merged_callback->callback = callback;
merged_callback->callback_data = callback_data;
merged_callback->wait_for_attributes = nautilus_g_str_list_copy (file_attributes);
- for (p = merged->details->directories; p != NULL; p = p->next) {
+ for (node = merged->details->directories; node != NULL; node = node->next) {
merged_callback->non_ready_directories = g_list_prepend
- (merged_callback->non_ready_directories, p->data);
+ (merged_callback->non_ready_directories, node->data);
}
/* Put it in the hash table. */
@@ -275,8 +244,11 @@ merged_call_when_ready (NautilusDirectory *directory,
}
/* 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);
+ for (node = merged->details->directories; node != NULL; node = node->next) {
+ nautilus_directory_call_when_ready
+ (node->data,
+ merged_callback->wait_for_attributes,
+ directory_ready_callback, merged_callback);
}
}
@@ -287,7 +259,7 @@ merged_cancel_callback (NautilusDirectory *directory,
{
NautilusMergedDirectory *merged;
MergedCallback search_key, *merged_callback;
- GList *p;
+ GList *node;
merged = NAUTILUS_MERGED_DIRECTORY (directory);
@@ -303,9 +275,9 @@ merged_cancel_callback (NautilusDirectory *directory,
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) {
+ for (node = merged_callback->non_ready_directories; node != NULL; node = node->next) {
nautilus_directory_cancel_callback
- (p->data,
+ (node->data,
directory_ready_callback, merged_callback);
}
merged_callback_destroy (merged_callback);
@@ -322,7 +294,7 @@ merged_file_monitor_add (NautilusDirectory *directory,
{
NautilusMergedDirectory *merged;
MergedMonitor *monitor;
- GList *p;
+ GList *node;
merged = NAUTILUS_MERGED_DIRECTORY (directory);
@@ -345,9 +317,9 @@ merged_file_monitor_add (NautilusDirectory *directory,
monitor->force_reload = force_reload;
/* Call through to the real directory add calls. */
- for (p = merged->details->directories; p != NULL; p = p->next) {
+ for (node = merged->details->directories; node != NULL; node = node->next) {
nautilus_directory_file_monitor_add
- (p->data, monitor,
+ (node->data, monitor,
monitor_hidden_files, monitor_backup_files,
file_attributes, force_reload);
}
@@ -360,7 +332,7 @@ merged_file_monitor_remove (NautilusDirectory *directory,
{
NautilusMergedDirectory *merged;
MergedMonitor *monitor;
- GList *p;
+ GList *node;
merged = NAUTILUS_MERGED_DIRECTORY (directory);
@@ -372,26 +344,44 @@ merged_file_monitor_remove (NautilusDirectory *directory,
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) {
+ for (node = merged->details->directories; node != NULL; node = node->next) {
nautilus_directory_file_monitor_remove
- (p->data, monitor);
+ (node->data, monitor);
}
nautilus_g_list_free_deep (monitor->monitor_attributes);
g_free (monitor);
}
+/* Return true if any directory in the list does. */
+static gboolean
+merged_contains_file (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ NautilusMergedDirectory *merged;
+ GList *node;
+
+ merged = NAUTILUS_MERGED_DIRECTORY (directory);
+
+ for (node = merged->details->directories; node != NULL; node = node->next) {
+ if (nautilus_directory_contains_file (node->data, file)) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
/* Return true only if all directories in the list do. */
static gboolean
merged_are_all_files_seen (NautilusDirectory *directory)
{
NautilusMergedDirectory *merged;
- GList *p;
+ GList *node;
merged = NAUTILUS_MERGED_DIRECTORY (directory);
- for (p = merged->details->directories; p != NULL; p = p->next) {
- if (!nautilus_directory_are_all_files_seen (p->data)) {
+ for (node = merged->details->directories; node != NULL; node = node->next) {
+ if (!nautilus_directory_are_all_files_seen (node->data)) {
return FALSE;
}
}
@@ -403,12 +393,12 @@ static gboolean
merged_is_not_empty (NautilusDirectory *directory)
{
NautilusMergedDirectory *merged;
- GList *p;
+ GList *node;
merged = NAUTILUS_MERGED_DIRECTORY (directory);
- for (p = merged->details->directories; p != NULL; p = p->next) {
- if (nautilus_directory_is_not_empty (p->data)) {
+ for (node = merged->details->directories; node != NULL; node = node->next) {
+ if (nautilus_directory_is_not_empty (node->data)) {
return TRUE;
}
}
@@ -517,6 +507,12 @@ nautilus_merged_directory_add_real_directory (NautilusMergedDirectory *merged,
real_directory);
}
+GList *
+nautilus_merged_directory_get_real_directories (NautilusMergedDirectory *merged)
+{
+ return g_list_copy (merged->details->directories);
+}
+
static void
merged_callback_remove_directory_cover (gpointer key,
gpointer value,
diff --git a/libnautilus-extensions/nautilus-merged-directory.h b/libnautilus-extensions/nautilus-merged-directory.h
index 5a3f41a4d..ac8db0bd5 100644
--- a/libnautilus-extensions/nautilus-merged-directory.h
+++ b/libnautilus-extensions/nautilus-merged-directory.h
@@ -61,5 +61,6 @@ void nautilus_merged_directory_add_real_directory (NautilusMergedDirectory
NautilusDirectory *real_directory);
void nautilus_merged_directory_remove_real_directory (NautilusMergedDirectory *merged_directory,
NautilusDirectory *real_directory);
+GList * nautilus_merged_directory_get_real_directories (NautilusMergedDirectory *merged_directory);
#endif /* NAUTILUS_MERGED_DIRECTORY_H */
diff --git a/libnautilus-extensions/nautilus-trash-file.c b/libnautilus-extensions/nautilus-trash-file.c
index 7c5e9481f..6eb68aa41 100644
--- a/libnautilus-extensions/nautilus-trash-file.c
+++ b/libnautilus-extensions/nautilus-trash-file.c
@@ -26,17 +26,42 @@
#include <config.h>
#include "nautilus-trash-file.h"
+#include "nautilus-directory-notify.h"
+#include "nautilus-file-private.h"
#include "nautilus-file-utilities.h"
+#include "nautilus-glib-extensions.h"
#include "nautilus-gtk-macros.h"
#include "nautilus-trash-directory.h"
#include <gtk/gtksignal.h>
struct NautilusTrashFileDetails {
- NautilusTrashDirectory *as_directory;
+ NautilusTrashDirectory *trash_directory;
+
guint add_directory_connection_id;
guint remove_directory_connection_id;
+
+ GList *files;
+
+ GHashTable *callbacks;
+ GHashTable *monitors;
};
+typedef struct {
+ NautilusTrashFile *trash;
+ NautilusFileCallback callback;
+ gpointer callback_data;
+
+ GList *attributes;
+
+ GList *non_ready_files;
+} TrashCallback;
+
+typedef struct {
+ NautilusTrashFile *trash;
+
+ GList *attributes;
+} TrashMonitor;
+
static void nautilus_trash_file_initialize (gpointer object,
gpointer klass);
static void nautilus_trash_file_initialize_class (gpointer klass);
@@ -45,6 +70,187 @@ NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusTrashFile,
nautilus_trash_file,
NAUTILUS_TYPE_FILE)
+static guint
+trash_callback_hash (gconstpointer trash_callback_as_pointer)
+{
+ const TrashCallback *trash_callback;
+
+ trash_callback = trash_callback_as_pointer;
+ return GPOINTER_TO_UINT (trash_callback->callback)
+ ^ GPOINTER_TO_UINT (trash_callback->callback_data);
+}
+
+static gboolean
+trash_callback_equal (gconstpointer trash_callback_as_pointer,
+ gconstpointer trash_callback_as_pointer_2)
+{
+ 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;
+}
+
+static void
+trash_callback_destroy (TrashCallback *trash_callback)
+{
+ g_assert (trash_callback != NULL);
+ g_assert (NAUTILUS_IS_TRASH_FILE (trash_callback->trash));
+
+ nautilus_g_list_free_deep (trash_callback->attributes);
+ g_list_free (trash_callback->non_ready_files);
+ g_free (trash_callback);
+}
+
+static void
+trash_callback_check_done (TrashCallback *trash_callback)
+{
+ /* Check if we are ready. */
+ if (trash_callback->non_ready_files != NULL) {
+ return;
+ }
+
+ /* Remove from the hash table before sending it. */
+ g_hash_table_remove (trash_callback->trash->details->callbacks,
+ trash_callback);
+
+ /* We are ready, so do the real callback. */
+ (* trash_callback->callback) (NAUTILUS_FILE (trash_callback->trash),
+ trash_callback->callback_data);
+
+ /* And we are done. */
+ trash_callback_destroy (trash_callback);
+}
+
+static void
+trash_callback_remove_file (TrashCallback *trash_callback,
+ NautilusFile *file)
+{
+ trash_callback->non_ready_files = g_list_remove
+ (trash_callback->non_ready_files, file);
+ trash_callback_check_done (trash_callback);
+}
+
+static void
+ready_callback (NautilusFile *file,
+ gpointer callback_data)
+{
+ TrashCallback *trash_callback;
+
+ g_assert (NAUTILUS_IS_FILE (file));
+ g_assert (callback_data != NULL);
+
+ trash_callback = callback_data;
+ g_assert (g_list_find (trash_callback->non_ready_files, file) != NULL);
+
+ trash_callback_remove_file (trash_callback, file);
+}
+
+static void
+real_file_changed_callback (NautilusFile *real_file,
+ gpointer callback_data)
+{
+ NautilusTrashFile *trash_file;
+
+ trash_file = NAUTILUS_TRASH_FILE (callback_data);
+ nautilus_file_changed (NAUTILUS_FILE (trash_file));
+}
+
+static void
+monitor_add_file (gpointer key,
+ gpointer value,
+ gpointer callback_data)
+{
+ TrashMonitor *monitor;
+
+ monitor = value;
+ nautilus_file_monitor_add
+ (NAUTILUS_FILE (callback_data),
+ monitor,
+ monitor->attributes);
+}
+
+static void
+add_real_file (NautilusTrashFile *trash,
+ NautilusFile *real_file)
+{
+ g_return_if_fail (NAUTILUS_IS_TRASH_FILE (trash));
+ g_return_if_fail (NAUTILUS_IS_FILE (real_file));
+ g_return_if_fail (!NAUTILUS_IS_TRASH_FILE (real_file));
+ g_return_if_fail (g_list_find (trash->details->files, real_file) == NULL);
+
+ nautilus_file_ref (real_file);
+ trash->details->files = g_list_prepend
+ (trash->details->files, real_file);
+
+ gtk_signal_connect (GTK_OBJECT (real_file),
+ "changed",
+ real_file_changed_callback,
+ trash);
+
+ /* Add the file to any extant monitors. */
+ g_hash_table_foreach (trash->details->monitors,
+ monitor_add_file,
+ real_file);
+}
+
+static void
+trash_callback_remove_file_cover (gpointer key,
+ gpointer value,
+ gpointer callback_data)
+{
+ trash_callback_remove_file
+ (value, NAUTILUS_FILE (callback_data));
+}
+
+static void
+monitor_remove_file (gpointer key,
+ gpointer value,
+ gpointer callback_data)
+{
+ nautilus_file_monitor_remove
+ (NAUTILUS_FILE (callback_data), value);
+}
+
+static void
+remove_real_file (NautilusTrashFile *trash,
+ NautilusFile *real_file)
+{
+ g_return_if_fail (NAUTILUS_IS_TRASH_FILE (trash));
+ g_return_if_fail (NAUTILUS_IS_FILE (real_file));
+ g_return_if_fail (g_list_find (trash->details->files, real_file) != NULL);
+
+ nautilus_g_hash_table_safe_for_each
+ (trash->details->callbacks,
+ trash_callback_remove_file_cover,
+ real_file);
+ g_hash_table_foreach
+ (trash->details->monitors,
+ monitor_remove_file,
+ real_file);
+
+ gtk_signal_disconnect_by_func (GTK_OBJECT (real_file),
+ real_file_changed_callback,
+ trash);
+
+ trash->details->files = g_list_remove
+ (trash->details->files, real_file);
+ nautilus_file_unref (real_file);
+}
+
+static void
+add_real_file_given_directory (NautilusTrashFile *trash_file,
+ NautilusDirectory *real_directory)
+{
+ NautilusFile *real_file;
+
+ real_file = nautilus_directory_get_corresponding_file (real_directory);
+ add_real_file (trash_file, real_file);
+ nautilus_file_unref (real_file);
+}
+
static void
add_directory_callback (NautilusTrashDirectory *trash_directory,
NautilusDirectory *real_directory,
@@ -54,7 +260,11 @@ add_directory_callback (NautilusTrashDirectory *trash_directory,
g_assert (NAUTILUS_IS_DIRECTORY (real_directory));
g_assert (!NAUTILUS_IS_MERGED_DIRECTORY (real_directory));
g_assert (NAUTILUS_IS_TRASH_FILE (trash_file));
- g_assert (trash_file->details->as_directory == trash_directory);
+ g_assert (trash_file->details->trash_directory == trash_directory);
+
+ add_real_file_given_directory (trash_file, real_directory);
+
+ nautilus_file_changed (NAUTILUS_FILE (trash_file));
}
static void
@@ -62,11 +272,324 @@ remove_directory_callback (NautilusTrashDirectory *trash_directory,
NautilusDirectory *real_directory,
NautilusTrashFile *trash_file)
{
+ NautilusFile *real_file;
+
g_assert (NAUTILUS_IS_TRASH_DIRECTORY (trash_directory));
g_assert (NAUTILUS_IS_DIRECTORY (real_directory));
g_assert (!NAUTILUS_IS_MERGED_DIRECTORY (real_directory));
g_assert (NAUTILUS_IS_TRASH_FILE (trash_file));
- g_assert (trash_file->details->as_directory == trash_directory);
+ g_assert (trash_file->details->trash_directory == trash_directory);
+
+ real_file = nautilus_directory_get_corresponding_file (real_directory);
+ remove_real_file (trash_file, real_file);
+ nautilus_file_unref (real_file);
+
+ nautilus_file_changed (NAUTILUS_FILE (trash_file));
+}
+
+static void
+trash_file_call_when_ready (NautilusFile *file,
+ GList *file_attributes,
+ NautilusFileCallback callback,
+ gpointer callback_data)
+
+{
+ NautilusTrashFile *trash;
+ TrashCallback search_key, *trash_callback;
+ GList *node;
+
+ trash = NAUTILUS_TRASH_FILE (file);
+
+ /* 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");
+ 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->attributes = nautilus_g_str_list_copy (file_attributes);
+ for (node = trash->details->files; node != NULL; node = node->next) {
+ trash_callback->non_ready_files = g_list_prepend
+ (trash_callback->non_ready_files, node->data);
+ }
+
+ /* Put it in the hash table. */
+ g_hash_table_insert (trash->details->callbacks,
+ trash_callback, trash_callback);
+
+ /* Handle the pathological case where there are no files. */
+ if (trash->details->files == NULL) {
+ trash_callback_check_done (trash_callback);
+ }
+
+ /* Now connect to each file's call_when_ready. */
+ for (node = trash->details->files; node != NULL; node = node->next) {
+ nautilus_file_call_when_ready
+ (node->data,
+ trash_callback->attributes,
+ ready_callback, trash_callback);
+ }
+}
+
+static void
+trash_file_cancel_call_when_ready (NautilusFile *file,
+ NautilusFileCallback callback,
+ gpointer callback_data)
+{
+ NautilusTrashFile *trash;
+ TrashCallback search_key, *trash_callback;
+ GList *node;
+
+ trash = NAUTILUS_TRASH_FILE (file);
+
+ /* 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) {
+ return;
+ }
+
+ /* Remove from the hash table before working with it. */
+ g_hash_table_remove (trash_callback->trash->details->callbacks, trash_callback);
+
+ /* Tell all the directories to cancel the call. */
+ for (node = trash_callback->non_ready_files; node != NULL; node = node->next) {
+ nautilus_file_cancel_call_when_ready
+ (node->data,
+ ready_callback, trash_callback);
+ }
+ trash_callback_destroy (trash_callback);
+}
+
+static gboolean
+trash_file_check_if_ready (NautilusFile *file,
+ GList *file_attributes)
+{
+ NautilusTrashFile *trash;
+ GList *node;
+
+ trash = NAUTILUS_TRASH_FILE (file);
+
+ for (node = trash->details->files; node != NULL; node = node->next) {
+ if (!nautilus_file_check_if_ready (node->data,
+ file_attributes)) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static void
+trash_file_monitor_add (NautilusFile *file,
+ gconstpointer client,
+ GList *attributes)
+{
+ NautilusTrashFile *trash;
+ TrashMonitor *monitor;
+ GList *node;
+
+ trash = NAUTILUS_TRASH_FILE (file);
+
+ /* Map the client to a unique value so this doesn't interfere
+ * with direct monitoring of the file by the same client.
+ */
+ monitor = g_hash_table_lookup (trash->details->monitors, client);
+ if (monitor != NULL) {
+ g_assert (monitor->trash == trash);
+ nautilus_g_list_free_deep (monitor->attributes);
+ } else {
+ monitor = g_new0 (TrashMonitor, 1);
+ monitor->trash = trash;
+ g_hash_table_insert (trash->details->monitors,
+ (gpointer) client, monitor);
+ }
+ monitor->attributes = nautilus_g_str_list_copy (attributes);
+
+ for (node = trash->details->files; node != NULL; node = node->next) {
+ nautilus_file_monitor_add (node->data, monitor, attributes);
+ }
+}
+
+static void
+trash_file_monitor_remove (NautilusFile *file,
+ gconstpointer client)
+{
+ NautilusTrashFile *trash;
+ TrashMonitor *monitor;
+ GList *node;
+
+ trash = NAUTILUS_TRASH_FILE (file);
+
+ /* Map the client to the value used by the earlier add call. */
+ monitor = g_hash_table_lookup (trash->details->monitors, client);
+ if (monitor == NULL) {
+ return;
+ }
+ g_hash_table_remove (trash->details->monitors, client);
+
+ /* Call through to the real file remove calls. */
+ for (node = trash->details->files; node != NULL; node = node->next) {
+ nautilus_file_monitor_remove (node->data, monitor);
+ }
+
+ nautilus_g_list_free_deep (monitor->attributes);
+ g_free (monitor);
+}
+
+static GnomeVFSFileType
+trash_file_get_file_type (NautilusFile *file)
+{
+ return GNOME_VFS_FILE_TYPE_DIRECTORY;
+}
+
+static gboolean
+trash_file_get_item_count (NautilusFile *file,
+ guint *count,
+ gboolean *count_unreadable)
+{
+ NautilusTrashFile *trash;
+ GList *node;
+ guint one_count, one_unreadable;
+ gboolean got_count;
+
+ trash = NAUTILUS_TRASH_FILE (file);
+
+ got_count = TRUE;
+ if (count != NULL) {
+ *count = 0;
+ }
+ if (count_unreadable != NULL) {
+ *count_unreadable = FALSE;
+ }
+
+ for (node = trash->details->files; node != NULL; node = node->next) {
+ if (!nautilus_file_get_directory_item_count (node->data,
+ &one_count,
+ &one_unreadable)) {
+ got_count = FALSE;
+ }
+
+ if (count != NULL) {
+ *count += one_count;
+ }
+ if (count_unreadable != NULL && one_unreadable) {
+ *count_unreadable = TRUE;
+ }
+ }
+
+ return got_count;
+}
+
+static NautilusRequestStatus
+trash_file_get_deep_counts (NautilusFile *file,
+ guint *directory_count,
+ guint *file_count,
+ guint *unreadable_directory_count,
+ GnomeVFSFileSize *total_size)
+{
+ NautilusTrashFile *trash;
+ GList *node;
+ NautilusRequestStatus status, one_status;
+ guint one_directory_count, one_file_count, one_unreadable_directory_count;
+ GnomeVFSFileSize one_total_size;
+
+ trash = NAUTILUS_TRASH_FILE (file);
+
+ status = NAUTILUS_REQUEST_DONE;
+ if (directory_count != NULL) {
+ *directory_count = 0;
+ }
+ if (file_count != NULL) {
+ *file_count = 0;
+ }
+ if (unreadable_directory_count != NULL) {
+ *unreadable_directory_count = 0;
+ }
+ if (total_size != NULL) {
+ *total_size = 0;
+ }
+
+ for (node = trash->details->files; node != NULL; node = node->next) {
+ one_status = nautilus_file_get_deep_counts
+ (node->data,
+ &one_directory_count,
+ &one_file_count,
+ &one_unreadable_directory_count,
+ &one_total_size);
+
+ if (one_status < status) {
+ status = one_status;
+ }
+ if (directory_count != NULL) {
+ *directory_count += one_directory_count;
+ }
+ if (file_count != NULL) {
+ *file_count += one_file_count;
+ }
+ if (unreadable_directory_count != NULL) {
+ *unreadable_directory_count += one_unreadable_directory_count;
+ }
+ if (total_size != NULL) {
+ *total_size += one_total_size;
+ }
+ }
+
+ return status;
+}
+
+static gboolean
+trash_file_get_date (NautilusFile *file,
+ NautilusDateType date_type,
+ time_t *date)
+{
+ NautilusTrashFile *trash;
+ GList *node;
+ gboolean got_at_least_one;
+ gboolean got_all;
+ time_t one_date;
+
+ trash = NAUTILUS_TRASH_FILE (file);
+
+ got_at_least_one = FALSE;
+ got_all = TRUE;
+
+ for (node = trash->details->files; node != NULL; node = node->next) {
+ if (nautilus_file_get_date (node->data,
+ date_type,
+ &one_date)) {
+ if (!got_at_least_one) {
+ got_at_least_one = TRUE;
+ if (date != NULL) {
+ *date = one_date;
+ }
+ } else {
+ if (date != NULL && one_date > *date) {
+ *date = one_date;
+ }
+ }
+ } else {
+ got_all = FALSE;
+ }
+ }
+
+ return got_at_least_one && got_all;
+}
+
+
+static void
+remove_all_real_files (NautilusTrashFile *trash)
+{
+ while (trash->details->files != NULL) {
+ remove_real_file (trash, trash->details->files->data);
+ }
}
static void
@@ -74,13 +597,18 @@ nautilus_trash_file_initialize (gpointer object, gpointer klass)
{
NautilusTrashFile *trash_file;
NautilusTrashDirectory *trash_directory;
+ GList *real_directories, *node;
trash_file = NAUTILUS_TRASH_FILE (object);
trash_directory = NAUTILUS_TRASH_DIRECTORY (nautilus_directory_get (NAUTILUS_TRASH_URI));
trash_file->details = g_new0 (NautilusTrashFileDetails, 1);
- trash_file->details->as_directory = trash_directory;
+ trash_file->details->trash_directory = trash_directory;
+
+ trash_file->details->callbacks = g_hash_table_new
+ (trash_callback_hash, trash_callback_equal);
+ trash_file->details->monitors = g_hash_table_new (NULL, NULL);
trash_file->details->add_directory_connection_id = gtk_signal_connect
(GTK_OBJECT (trash_directory),
@@ -92,6 +620,13 @@ nautilus_trash_file_initialize (gpointer object, gpointer klass)
"remove_real_directory",
remove_directory_callback,
trash_file);
+
+ real_directories = nautilus_merged_directory_get_real_directories
+ (NAUTILUS_MERGED_DIRECTORY (trash_directory));
+ for (node = real_directories; node != NULL; node = node->next) {
+ add_real_file_given_directory (trash_file, node->data);
+ }
+ g_list_free (real_directories);
}
static void
@@ -101,15 +636,29 @@ trash_destroy (GtkObject *object)
NautilusTrashDirectory *trash_directory;
trash_file = NAUTILUS_TRASH_FILE (object);
- trash_directory = trash_file->details->as_directory;
+ trash_directory = trash_file->details->trash_directory;
+
+ remove_all_real_files (trash_file);
+
+ if (g_hash_table_size (trash_file->details->callbacks) != 0) {
+ g_warning ("call_when_ready still pending when trash virtual file is destroyed");
+ }
+ if (g_hash_table_size (trash_file->details->monitors) != 0) {
+ g_warning ("file monitor still active when trash virtual file is destroyed");
+ }
gtk_signal_disconnect (GTK_OBJECT (trash_directory),
trash_file->details->add_directory_connection_id);
gtk_signal_disconnect (GTK_OBJECT (trash_directory),
trash_file->details->remove_directory_connection_id);
- nautilus_directory_unref (NAUTILUS_DIRECTORY (trash_directory));
+
+ g_hash_table_destroy (trash_file->details->callbacks);
+ g_hash_table_destroy (trash_file->details->monitors);
+
g_free (trash_file->details);
+ nautilus_directory_unref (NAUTILUS_DIRECTORY (trash_directory));
+
NAUTILUS_CALL_PARENT_CLASS (GTK_OBJECT_CLASS, destroy, (object));
}
@@ -124,5 +673,13 @@ nautilus_trash_file_initialize_class (gpointer klass)
object_class->destroy = trash_destroy;
- /* file_class-> */
+ file_class->monitor_add = trash_file_monitor_add;
+ file_class->monitor_remove = trash_file_monitor_remove;
+ file_class->call_when_ready = trash_file_call_when_ready;
+ file_class->cancel_call_when_ready = trash_file_cancel_call_when_ready;
+ file_class->check_if_ready = trash_file_check_if_ready;
+ file_class->get_file_type = trash_file_get_file_type;
+ file_class->get_item_count = trash_file_get_item_count;
+ file_class->get_deep_counts = trash_file_get_deep_counts;
+ file_class->get_date = trash_file_get_date;
}
diff --git a/libnautilus-extensions/nautilus-vfs-file.c b/libnautilus-extensions/nautilus-vfs-file.c
index 455ac59c7..eba08921b 100644
--- a/libnautilus-extensions/nautilus-vfs-file.c
+++ b/libnautilus-extensions/nautilus-vfs-file.c
@@ -94,6 +94,13 @@ vfs_file_check_if_ready (NautilusFile *file,
file_attributes);
}
+static GnomeVFSFileType
+vfs_file_get_file_type (NautilusFile *file)
+{
+ return nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_TYPE)
+ ? GNOME_VFS_FILE_TYPE_UNKNOWN : file->details->info->type;
+}
+
static gboolean
vfs_file_get_item_count (NautilusFile *file,
guint *count,
@@ -103,10 +110,14 @@ vfs_file_get_item_count (NautilusFile *file,
*count_unreadable = file->details->directory_count_failed;
}
if (!file->details->got_directory_count) {
- *count = 0;
+ if (count != NULL) {
+ *count = 0;
+ }
return FALSE;
}
- *count = file->details->directory_count;
+ if (count != NULL) {
+ *count = file->details->directory_count;
+ }
return TRUE;
}
@@ -163,6 +174,61 @@ vfs_file_get_deep_counts (NautilusFile *file,
return NAUTILUS_REQUEST_DONE;
}
+static gboolean
+vfs_file_get_date (NautilusFile *file,
+ NautilusDateType date_type,
+ time_t *date)
+{
+ switch (date_type) {
+ case NAUTILUS_DATE_TYPE_CHANGED:
+ /* Before we have info on a file, the date is unknown. */
+ if (nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_CTIME)) {
+ return FALSE;
+ }
+ if (date != NULL) {
+ *date = file->details->info->ctime;
+ }
+ return TRUE;
+ case NAUTILUS_DATE_TYPE_ACCESSED:
+ /* Before we have info on a file, the date is unknown. */
+ if (nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_ATIME)) {
+ return FALSE;
+ }
+ if (date != NULL) {
+ *date = file->details->info->atime;
+ }
+ return TRUE;
+ case NAUTILUS_DATE_TYPE_MODIFIED:
+ /* Before we have info on a file, the date is unknown. */
+ if (nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_MTIME)) {
+ return FALSE;
+ }
+ if (date != NULL) {
+ *date = file->details->info->mtime;
+ }
+ return TRUE;
+ case NAUTILUS_DATE_TYPE_PERMISSIONS_CHANGED:
+ /* Before we have info on a file, the date is unknown. */
+ if (nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_MTIME) ||
+ nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_CTIME)) {
+ return FALSE;
+ }
+ /* mtime is when the contents changed; ctime is when the
+ * contents or the permissions (inc. owner/group) changed.
+ * So we can only know when the permissions changed if mtime
+ * and ctime are different.
+ */
+ if (file->details->info->mtime == file->details->info->ctime) {
+ return FALSE;
+ }
+ if (date != NULL) {
+ *date = file->details->info->ctime;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
static void
nautilus_vfs_file_initialize (gpointer object, gpointer klass)
{
@@ -195,6 +261,8 @@ nautilus_vfs_file_initialize_class (gpointer klass)
file_class->call_when_ready = vfs_file_call_when_ready;
file_class->cancel_call_when_ready = vfs_file_cancel_call_when_ready;
file_class->check_if_ready = vfs_file_check_if_ready;
+ file_class->get_file_type = vfs_file_get_file_type;
file_class->get_item_count = vfs_file_get_item_count;
file_class->get_deep_counts = vfs_file_get_deep_counts;
+ file_class->get_date = vfs_file_get_date;
}
diff --git a/libnautilus-extensions/nautilus-view-identifier.c b/libnautilus-extensions/nautilus-view-identifier.c
index f80fc92e4..6209bd452 100644
--- a/libnautilus-extensions/nautilus-view-identifier.c
+++ b/libnautilus-extensions/nautilus-view-identifier.c
@@ -55,8 +55,8 @@ nautilus_view_identifier_copy (NautilusViewIdentifier *identifier)
return nautilus_view_identifier_new (identifier->iid, identifier->name);
}
-/* Returns a list of languages (with one element), containing
- the LANG or LANGUAGE environment setting.
+/* Returns a list of languages, containing
+ the LANG or LANGUAGE environment setting (with and without region code).
The elements in the returned list must be freed */
static GSList *
get_lang_list (void)
@@ -96,8 +96,9 @@ get_lang_list (void)
lang string */
if (!nautilus_str_is_empty (lang_with_locale)) {
retval = g_slist_prepend (retval,
- lang_with_locale);
+ g_strdup (lang_with_locale));
}
+ g_free (lang_with_locale);
if (!nautilus_str_is_empty (lang)) {
retval = g_slist_prepend (retval, g_strdup (lang));
}
diff --git a/libnautilus-private/nautilus-directory-async.c b/libnautilus-private/nautilus-directory-async.c
index b065b89b0..d0dc48832 100644
--- a/libnautilus-private/nautilus-directory-async.c
+++ b/libnautilus-private/nautilus-directory-async.c
@@ -1414,6 +1414,7 @@ directory_load_callback (GnomeVFSAsyncHandle *handle,
directory = NAUTILUS_DIRECTORY (callback_data);
+ g_assert (directory->details->directory_load_in_progress != NULL);
g_assert (directory->details->directory_load_in_progress == handle);
/* Move items from the list onto our pending queue.
diff --git a/libnautilus-private/nautilus-file-operations.c b/libnautilus-private/nautilus-file-operations.c
index 03ce35c59..f58ee5f93 100644
--- a/libnautilus-private/nautilus-file-operations.c
+++ b/libnautilus-private/nautilus-file-operations.c
@@ -1000,22 +1000,22 @@ handle_transfer_overwrite (const GnomeVFSXferProgressInfo *progress_info,
/* Handle special case files such as Trash, mount links and home directory */
if (is_special_link (progress_info->target_name)) {
- formatted_name = extract_and_ellipsize_file_name_for_dialog (progress_info->target_name);
+ formatted_name = extract_and_ellipsize_file_name_for_dialog
+ (progress_info->target_name);
if (transfer_info->kind == TRANSFER_MOVE) {
text = g_strdup_printf (_("\"%s\" could not be moved to the new location, "
- "because the name is already used for a special item that "
- "cannot be removed or replaced. "
+ "because its name is already used for a special item that "
+ "cannot be removed or replaced.\n\n"
"If you still want to move \"%s\", rename it and try again."),
formatted_name, formatted_name);
} else {
text = g_strdup_printf (_("\"%s\" could not be copied to the new location, "
- "because the name is already used for a special item that "
- "cannot be removed or replaced. "
+ "because its name is already used for a special item that "
+ "cannot be removed or replaced.\n\n"
"If you still want to copy \"%s\", rename it and try again."),
formatted_name, formatted_name);
-
- };
+ }
nautilus_simple_dialog (parent_for_error_dialog (transfer_info), TRUE, text,
_("Unable to replace file."), _("OK"), NULL, NULL);
diff --git a/libnautilus-private/nautilus-file-private.h b/libnautilus-private/nautilus-file-private.h
index de0a113ab..ed981017f 100644
--- a/libnautilus-private/nautilus-file-private.h
+++ b/libnautilus-private/nautilus-file-private.h
@@ -99,36 +99,41 @@ struct NautilusFileDetails
nautilus_boolean_bit activation_uri_is_up_to_date : 1;
};
-NautilusFile *nautilus_file_new_from_info (NautilusDirectory *directory,
- GnomeVFSFileInfo *info);
-NautilusFile *nautilus_file_get_existing (const char *uri);
-void nautilus_file_emit_changed (NautilusFile *file);
-void nautilus_file_mark_gone (NautilusFile *file);
-char * nautilus_extract_top_left_text (const char *text,
- int length);
-gboolean nautilus_file_contains_text (NautilusFile *file);
-void nautilus_file_set_directory (NautilusFile *file,
- NautilusDirectory *directory);
+NautilusFile *nautilus_file_new_from_info (NautilusDirectory *directory,
+ GnomeVFSFileInfo *info);
+NautilusFile *nautilus_file_get_existing (const char *uri);
+void nautilus_file_emit_changed (NautilusFile *file);
+void nautilus_file_mark_gone (NautilusFile *file);
+gboolean nautilus_file_info_missing (NautilusFile *file,
+ GnomeVFSFileInfoFields needed_mask);
+char * nautilus_extract_top_left_text (const char *text,
+ int length);
+gboolean nautilus_file_contains_text (NautilusFile *file);
+void nautilus_file_set_directory (NautilusFile *file,
+ NautilusDirectory *directory);
+gboolean nautilus_file_get_date (NautilusFile *file,
+ NautilusDateType date_type,
+ time_t *date);
/* Compare file's state with a fresh file info struct, return FALSE if
* no change, update file and return TRUE if the file info contains
* new state. */
-gboolean nautilus_file_update_info (NautilusFile *file,
- GnomeVFSFileInfo *info);
-gboolean nautilus_file_update_name (NautilusFile *file,
- const char *name);
+gboolean nautilus_file_update_info (NautilusFile *file,
+ GnomeVFSFileInfo *info);
+gboolean nautilus_file_update_name (NautilusFile *file,
+ const char *name);
/* Return true if the top lefts of files in this directory should be
* fetched, according to the preference settings.
*/
-gboolean nautilus_file_should_get_top_left_text (NautilusFile *file);
+gboolean nautilus_file_should_get_top_left_text (NautilusFile *file);
/* Mark specified attributes for this file out of date without canceling current
* I/O or kicking off new I/O.
*/
-void nautilus_file_invalidate_attributes_internal (NautilusFile *file,
- GList *file_attributes);
+void nautilus_file_invalidate_attributes_internal (NautilusFile *file,
+ GList *file_attributes);
/* Recognizing special file names. */
-gboolean nautilus_file_name_matches_hidden_pattern (const char *name_or_relative_uri);
-gboolean nautilus_file_name_matches_backup_pattern (const char *name_or_relative_uri);
+gboolean nautilus_file_name_matches_hidden_pattern (const char *name_or_relative_uri);
+gboolean nautilus_file_name_matches_backup_pattern (const char *name_or_relative_uri);
diff --git a/libnautilus-private/nautilus-file.c b/libnautilus-private/nautilus-file.c
index d9cd0c162..d4ea4a908 100644
--- a/libnautilus-private/nautilus-file.c
+++ b/libnautilus-private/nautilus-file.c
@@ -37,6 +37,7 @@
#include "nautilus-lib-self-check-functions.h"
#include "nautilus-link.h"
#include "nautilus-string.h"
+#include "nautilus-trash-directory.h"
#include "nautilus-trash-file.h"
#include "nautilus-vfs-file.h"
#include <ctype.h>
@@ -69,13 +70,6 @@ extern void eazel_dump_stack_trace (const char *print_prefix,
/* Name to use to tag metadata for the directory itself. */
#define FILE_NAME_FOR_DIRECTORY_METADATA "."
-typedef enum {
- NAUTILUS_DATE_TYPE_MODIFIED,
- NAUTILUS_DATE_TYPE_CHANGED,
- NAUTILUS_DATE_TYPE_ACCESSED,
- NAUTILUS_DATE_TYPE_PERMISSIONS_CHANGED
-} NautilusDateType;
-
typedef struct {
NautilusFile *file;
GnomeVFSAsyncHandle *handle;
@@ -133,7 +127,8 @@ nautilus_file_initialize (NautilusFile *file)
static NautilusFile *
nautilus_file_new_from_relative_uri (NautilusDirectory *directory,
- const char *relative_uri)
+ const char *relative_uri,
+ gboolean self_owned)
{
NautilusFile *file;
@@ -141,7 +136,11 @@ nautilus_file_new_from_relative_uri (NautilusDirectory *directory,
g_return_val_if_fail (relative_uri != NULL, NULL);
g_return_val_if_fail (relative_uri[0] != '\0', NULL);
- file = NAUTILUS_FILE (gtk_object_new (NAUTILUS_TYPE_VFS_FILE, NULL));
+ if (self_owned && NAUTILUS_IS_TRASH_DIRECTORY (directory)) {
+ file = NAUTILUS_FILE (gtk_object_new (NAUTILUS_TYPE_TRASH_FILE, NULL));
+ } else {
+ file = NAUTILUS_FILE (gtk_object_new (NAUTILUS_TYPE_VFS_FILE, NULL));
+ }
gtk_object_ref (GTK_OBJECT (file));
gtk_object_sink (GTK_OBJECT (file));
@@ -158,8 +157,8 @@ nautilus_file_new_from_relative_uri (NautilusDirectory *directory,
return file;
}
-static gboolean
-info_missing (NautilusFile *file, GnomeVFSFileInfoFields needed_mask)
+gboolean
+nautilus_file_info_missing (NautilusFile *file, GnomeVFSFileInfoFields needed_mask)
{
GnomeVFSFileInfo *info;
@@ -185,7 +184,7 @@ modify_link_hash_table (NautilusFile *file,
GList *list;
/* Check if there is a symlink name. If none, we are OK. */
- if (info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_SYMLINK_NAME)) {
+ if (nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_SYMLINK_NAME)) {
return;
}
symlink_name = file->details->info->symlink_name;
@@ -356,7 +355,7 @@ nautilus_file_get_internal (const char *uri, gboolean create)
if (file != NULL) {
nautilus_file_ref (file);
} else if (create) {
- file = nautilus_file_new_from_relative_uri (directory, relative_uri);
+ file = nautilus_file_new_from_relative_uri (directory, relative_uri, self_owned);
if (self_owned) {
g_assert (directory->details->as_file == NULL);
directory->details->as_file = file;
@@ -1077,7 +1076,7 @@ update_link (NautilusFile *link_file, NautilusFile *target_file)
{
g_assert (NAUTILUS_IS_FILE (link_file));
g_assert (NAUTILUS_IS_FILE (target_file));
- g_assert (!info_missing (link_file, GNOME_VFS_FILE_INFO_FIELDS_SYMLINK_NAME));
+ g_assert (!nautilus_file_info_missing (link_file, GNOME_VFS_FILE_INFO_FIELDS_SYMLINK_NAME));
/* FIXME bugzilla.eazel.com 2044: If we don't put any code
* here then the hash table is a waste of time.
@@ -2159,7 +2158,29 @@ nautilus_file_get_uri_scheme (NautilusFile *file)
colon - file->details->directory->details->uri);
}
+gboolean
+nautilus_file_get_date (NautilusFile *file,
+ NautilusDateType date_type,
+ time_t *date)
+{
+ if (date != NULL) {
+ *date = 0;
+ }
+
+ g_return_val_if_fail (date_type == NAUTILUS_DATE_TYPE_CHANGED
+ || date_type == NAUTILUS_DATE_TYPE_ACCESSED
+ || date_type == NAUTILUS_DATE_TYPE_MODIFIED
+ || date_type == NAUTILUS_DATE_TYPE_PERMISSIONS_CHANGED, FALSE);
+
+ if (file == NULL) {
+ return FALSE;
+ }
+ g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
+
+ return NAUTILUS_CALL_VIRTUAL (NAUTILUS_FILE_CLASS, file,
+ get_date, (file, date_type, date));
+}
/**
* nautilus_file_get_date_as_string:
@@ -2173,61 +2194,19 @@ nautilus_file_get_uri_scheme (NautilusFile *file)
**/
static char *
nautilus_file_get_date_as_string (NautilusFile *file, NautilusDateType date_type)
-{
- struct tm *file_time = NULL;
+{
+ time_t file_time_raw;
+ struct tm *file_time;
const char *format;
GDate *today;
GDate *file_date;
guint32 file_date_age;
- g_return_val_if_fail (date_type == NAUTILUS_DATE_TYPE_CHANGED
- || date_type == NAUTILUS_DATE_TYPE_ACCESSED
- || date_type == NAUTILUS_DATE_TYPE_MODIFIED
- || date_type == NAUTILUS_DATE_TYPE_PERMISSIONS_CHANGED, NULL);
-
- switch (date_type) {
- case NAUTILUS_DATE_TYPE_CHANGED:
- /* Before we have info on a file, the date is unknown. */
- if (info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_CTIME)) {
- return NULL;
- }
- file_time = localtime (&file->details->info->ctime);
- break;
- case NAUTILUS_DATE_TYPE_ACCESSED:
- /* Before we have info on a file, the date is unknown. */
- if (info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_ATIME)) {
- return NULL;
- }
- file_time = localtime (&file->details->info->atime);
- break;
- case NAUTILUS_DATE_TYPE_MODIFIED:
- /* Before we have info on a file, the date is unknown. */
- if (info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_MTIME)) {
- return NULL;
- }
- file_time = localtime (&file->details->info->mtime);
- break;
- case NAUTILUS_DATE_TYPE_PERMISSIONS_CHANGED:
- /* Before we have info on a file, the date is unknown. */
- if (info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_MTIME) ||
- info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_CTIME)) {
- return NULL;
- }
- /* mtime is when the contents changed; ctime is when the
- * contents or the permissions (inc. owner/group) changed.
- * So we can only know when the permissions changed if mtime
- * and ctime are different.
- */
- if (file->details->info->mtime == file->details->info->ctime) {
- return NULL;
- }
-
- file_time = localtime (&file->details->info->ctime);
- break;
- default:
- g_assert_not_reached ();
+ if (!nautilus_file_get_date (file, date_type, &file_time_raw)) {
+ return NULL;
}
+ file_time = localtime (&file_time_raw);
file_date = nautilus_g_date_new_tm (file_time);
today = g_date_new ();
@@ -2298,13 +2277,12 @@ nautilus_file_get_directory_item_count (NautilusFile *file,
guint *count,
gboolean *count_unreadable)
{
+ if (count != NULL) {
+ *count = 0;
+ }
if (count_unreadable != NULL) {
- *count_unreadable = 0;
+ *count_unreadable = FALSE;
}
-
- g_return_val_if_fail (count != NULL, FALSE);
-
- *count = 0;
g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
@@ -2414,7 +2392,7 @@ GnomeVFSFileSize
nautilus_file_get_size (NautilusFile *file)
{
/* Before we have info on the file, we don't know the size. */
- return info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_SIZE)
+ return nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_SIZE)
? 0 : file->details->info->size;
}
@@ -2431,7 +2409,7 @@ nautilus_file_get_size (NautilusFile *file)
gboolean
nautilus_file_can_get_permissions (NautilusFile *file)
{
- return !info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS);
+ return !nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS);
}
/**
@@ -2720,7 +2698,7 @@ nautilus_file_can_get_owner (NautilusFile *file)
* Can we trust the uid in the file info? Might
* there be garbage there? What will it do for non-local files?
*/
- return !info_missing (file, 0 /* FIXME bugzilla.eazel.com 644: GNOME_VFS_FILE_INFO_FIELDS_UID */);
+ return !nautilus_file_info_missing (file, 0 /* FIXME bugzilla.eazel.com 644: GNOME_VFS_FILE_INFO_FIELDS_UID */);
}
/**
@@ -2935,7 +2913,7 @@ nautilus_file_can_get_group (NautilusFile *file)
* Can we trust the gid in the file info? Might
* there be garbage there? What will it do for non-local files?
*/
- return !info_missing (file, 0 /* FIXME bugzilla.eazel.com 644: GNOME_VFS_FILE_INFO_FIELDS_GID */);
+ return !nautilus_file_info_missing (file, 0 /* FIXME bugzilla.eazel.com 644: GNOME_VFS_FILE_INFO_FIELDS_GID */);
}
/**
@@ -2955,7 +2933,7 @@ nautilus_file_get_group_name (NautilusFile *file)
struct group *group_info;
/* Before we have info on a file, the owner is unknown. */
- if (info_missing (file, 0 /* FIXME bugzilla.eazel.com 644: GNOME_VFS_FILE_INFO_FIELDS_GID */)) {
+ if (nautilus_file_info_missing (file, 0 /* FIXME bugzilla.eazel.com 644: GNOME_VFS_FILE_INFO_FIELDS_GID */)) {
return NULL;
}
@@ -3284,7 +3262,7 @@ nautilus_file_get_owner_as_string (NautilusFile *file, gboolean include_real_nam
* Can we trust the uid in the file info? Might
* there be garbage there? What will it do for non-local files?
*/
- if (info_missing (file, 0 /* FIXME bugzilla.eazel.com 644: GNOME_VFS_FILE_INFO_FIELDS_UID */)) {
+ if (nautilus_file_info_missing (file, 0 /* FIXME bugzilla.eazel.com 644: GNOME_VFS_FILE_INFO_FIELDS_UID */)) {
return NULL;
}
@@ -3357,7 +3335,7 @@ nautilus_file_get_size_as_string (NautilusFile *file)
return format_item_count_for_display (item_count, TRUE, TRUE);
}
- if (info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_SIZE)) {
+ if (nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_SIZE)) {
return NULL;
}
return gnome_vfs_format_file_size_for_display (file->details->info->size);
@@ -3750,8 +3728,10 @@ nautilus_file_get_type_as_string (NautilusFile *file)
GnomeVFSFileType
nautilus_file_get_file_type (NautilusFile *file)
{
- return info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_TYPE)
- ? GNOME_VFS_FILE_TYPE_UNKNOWN : file->details->info->type;
+ if (file == NULL) {
+ return GNOME_VFS_FILE_TYPE_UNKNOWN;
+ }
+ return NAUTILUS_CALL_VIRTUAL (NAUTILUS_FILE_CLASS, file, get_file_type, (file));
}
/**
@@ -3908,7 +3888,7 @@ nautilus_file_set_keywords (NautilusFile *file, GList *keywords)
gboolean
nautilus_file_is_symbolic_link (NautilusFile *file)
{
- return info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_FLAGS)
+ return nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_FLAGS)
? FALSE : (file->details->info->flags & GNOME_VFS_FILE_FLAGS_SYMLINK);
}
@@ -3948,7 +3928,7 @@ nautilus_file_get_symbolic_link_target_path (NautilusFile *file)
{
g_return_val_if_fail (nautilus_file_is_symbolic_link (file), NULL);
- return info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_SYMLINK_NAME)
+ return nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_SYMLINK_NAME)
? NULL
: g_strdup (file->details->info->symlink_name);
}
@@ -3980,12 +3960,6 @@ nautilus_file_is_nautilus_link (NautilusFile *file)
gboolean
nautilus_file_is_directory (NautilusFile *file)
{
- if (file == NULL) {
- return FALSE;
- }
-
- g_return_val_if_fail (NAUTILUS_IS_FILE (file), FALSE);
-
return nautilus_file_get_file_type (file) == GNOME_VFS_FILE_TYPE_DIRECTORY;
}
diff --git a/libnautilus-private/nautilus-file.h b/libnautilus-private/nautilus-file.h
index 2f0f26f74..9c7abe03f 100644
--- a/libnautilus-private/nautilus-file.h
+++ b/libnautilus-private/nautilus-file.h
@@ -288,6 +288,16 @@ struct NautilusFile {
NautilusFileDetails *details;
};
+/* This is actually a "protected" type, but it must be here so we can
+ * compile the get_date function pointer declaration below.
+ */
+typedef enum {
+ NAUTILUS_DATE_TYPE_MODIFIED,
+ NAUTILUS_DATE_TYPE_CHANGED,
+ NAUTILUS_DATE_TYPE_ACCESSED,
+ NAUTILUS_DATE_TYPE_PERMISSIONS_CHANGED
+} NautilusDateType;
+
typedef struct {
GtkObjectClass parent_slot;
@@ -309,6 +319,7 @@ typedef struct {
gpointer callback_data);
gboolean (* check_if_ready) (NautilusFile *file,
GList *attributes);
+ GnomeVFSFileType (* get_file_type) (NautilusFile *file);
gboolean (* get_item_count) (NautilusFile *file,
guint *count,
gboolean *count_unreadable);
@@ -317,6 +328,9 @@ typedef struct {
guint *file_count,
guint *unreadable_directory_count,
GnomeVFSFileSize *total_size);
+ gboolean (* get_date) (NautilusFile *file,
+ NautilusDateType type,
+ time_t *date);
} NautilusFileClass;
#endif /* NAUTILUS_FILE_H */
diff --git a/libnautilus-private/nautilus-icon-factory.c b/libnautilus-private/nautilus-icon-factory.c
index ed324c8c1..25cca9aaa 100644
--- a/libnautilus-private/nautilus-icon-factory.c
+++ b/libnautilus-private/nautilus-icon-factory.c
@@ -766,9 +766,6 @@ nautilus_icon_factory_get_icon_name_for_regular_file (NautilusFile *file)
icon_name = ICON_NAME_WEB;
} else if (nautilus_istr_has_prefix (uri, "eazel-install:")) {
icon_name = ICON_NAME_INSTALL;
- } else if (strcmp (uri, NAUTILUS_TRASH_URI) == 0) {
- icon_name = nautilus_trash_monitor_is_empty ()
- ? ICON_NAME_TRASH_EMPTY : ICON_NAME_TRASH_NOT_EMPTY;
} else {
if (nautilus_file_is_executable (file)
&& nautilus_strcasecmp (mime_type, "text/plain") != 0) {
@@ -798,7 +795,7 @@ nautilus_icon_factory_get_icon_name_for_directory (NautilusFile *file)
} else {
icon_name = ICON_NAME_DIRECTORY;
}
-
+
g_free (mime_type);
return icon_name;
@@ -809,6 +806,16 @@ nautilus_icon_factory_get_icon_name_for_directory (NautilusFile *file)
static const char *
nautilus_icon_factory_get_icon_name_for_file (NautilusFile *file)
{
+ char *uri;
+
+ uri = nautilus_file_get_uri (file);
+ if (strcmp (uri, NAUTILUS_TRASH_URI) == 0) {
+ g_free (uri);
+ return nautilus_trash_monitor_is_empty ()
+ ? ICON_NAME_TRASH_EMPTY : ICON_NAME_TRASH_NOT_EMPTY;
+ }
+ g_free (uri);
+
/* Get an icon name based on the file's type. */
switch (nautilus_file_get_file_type (file)) {
case GNOME_VFS_FILE_TYPE_DIRECTORY:
diff --git a/libnautilus-private/nautilus-merged-directory.c b/libnautilus-private/nautilus-merged-directory.c
index 2bea0815a..4d8bd3448 100644
--- a/libnautilus-private/nautilus-merged-directory.c
+++ b/libnautilus-private/nautilus-merged-directory.c
@@ -139,24 +139,6 @@ merged_callback_equal (gconstpointer merged_callback_as_pointer,
&& 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)
{
@@ -196,8 +178,6 @@ merged_callback_remove_directory (MergedCallback *merged_callback,
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);
}
@@ -220,18 +200,7 @@ directory_ready_callback (NautilusDirectory *directory,
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,
- directory_ready_callback, merged_callback);
+ merged_callback_remove_directory (merged_callback, directory);
}
static void
@@ -242,7 +211,7 @@ merged_call_when_ready (NautilusDirectory *directory,
{
NautilusMergedDirectory *merged;
MergedCallback search_key, *merged_callback;
- GList *p;
+ GList *node;
merged = NAUTILUS_MERGED_DIRECTORY (directory);
@@ -260,9 +229,9 @@ merged_call_when_ready (NautilusDirectory *directory,
merged_callback->callback = callback;
merged_callback->callback_data = callback_data;
merged_callback->wait_for_attributes = nautilus_g_str_list_copy (file_attributes);
- for (p = merged->details->directories; p != NULL; p = p->next) {
+ for (node = merged->details->directories; node != NULL; node = node->next) {
merged_callback->non_ready_directories = g_list_prepend
- (merged_callback->non_ready_directories, p->data);
+ (merged_callback->non_ready_directories, node->data);
}
/* Put it in the hash table. */
@@ -275,8 +244,11 @@ merged_call_when_ready (NautilusDirectory *directory,
}
/* 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);
+ for (node = merged->details->directories; node != NULL; node = node->next) {
+ nautilus_directory_call_when_ready
+ (node->data,
+ merged_callback->wait_for_attributes,
+ directory_ready_callback, merged_callback);
}
}
@@ -287,7 +259,7 @@ merged_cancel_callback (NautilusDirectory *directory,
{
NautilusMergedDirectory *merged;
MergedCallback search_key, *merged_callback;
- GList *p;
+ GList *node;
merged = NAUTILUS_MERGED_DIRECTORY (directory);
@@ -303,9 +275,9 @@ merged_cancel_callback (NautilusDirectory *directory,
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) {
+ for (node = merged_callback->non_ready_directories; node != NULL; node = node->next) {
nautilus_directory_cancel_callback
- (p->data,
+ (node->data,
directory_ready_callback, merged_callback);
}
merged_callback_destroy (merged_callback);
@@ -322,7 +294,7 @@ merged_file_monitor_add (NautilusDirectory *directory,
{
NautilusMergedDirectory *merged;
MergedMonitor *monitor;
- GList *p;
+ GList *node;
merged = NAUTILUS_MERGED_DIRECTORY (directory);
@@ -345,9 +317,9 @@ merged_file_monitor_add (NautilusDirectory *directory,
monitor->force_reload = force_reload;
/* Call through to the real directory add calls. */
- for (p = merged->details->directories; p != NULL; p = p->next) {
+ for (node = merged->details->directories; node != NULL; node = node->next) {
nautilus_directory_file_monitor_add
- (p->data, monitor,
+ (node->data, monitor,
monitor_hidden_files, monitor_backup_files,
file_attributes, force_reload);
}
@@ -360,7 +332,7 @@ merged_file_monitor_remove (NautilusDirectory *directory,
{
NautilusMergedDirectory *merged;
MergedMonitor *monitor;
- GList *p;
+ GList *node;
merged = NAUTILUS_MERGED_DIRECTORY (directory);
@@ -372,26 +344,44 @@ merged_file_monitor_remove (NautilusDirectory *directory,
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) {
+ for (node = merged->details->directories; node != NULL; node = node->next) {
nautilus_directory_file_monitor_remove
- (p->data, monitor);
+ (node->data, monitor);
}
nautilus_g_list_free_deep (monitor->monitor_attributes);
g_free (monitor);
}
+/* Return true if any directory in the list does. */
+static gboolean
+merged_contains_file (NautilusDirectory *directory,
+ NautilusFile *file)
+{
+ NautilusMergedDirectory *merged;
+ GList *node;
+
+ merged = NAUTILUS_MERGED_DIRECTORY (directory);
+
+ for (node = merged->details->directories; node != NULL; node = node->next) {
+ if (nautilus_directory_contains_file (node->data, file)) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
/* Return true only if all directories in the list do. */
static gboolean
merged_are_all_files_seen (NautilusDirectory *directory)
{
NautilusMergedDirectory *merged;
- GList *p;
+ GList *node;
merged = NAUTILUS_MERGED_DIRECTORY (directory);
- for (p = merged->details->directories; p != NULL; p = p->next) {
- if (!nautilus_directory_are_all_files_seen (p->data)) {
+ for (node = merged->details->directories; node != NULL; node = node->next) {
+ if (!nautilus_directory_are_all_files_seen (node->data)) {
return FALSE;
}
}
@@ -403,12 +393,12 @@ static gboolean
merged_is_not_empty (NautilusDirectory *directory)
{
NautilusMergedDirectory *merged;
- GList *p;
+ GList *node;
merged = NAUTILUS_MERGED_DIRECTORY (directory);
- for (p = merged->details->directories; p != NULL; p = p->next) {
- if (nautilus_directory_is_not_empty (p->data)) {
+ for (node = merged->details->directories; node != NULL; node = node->next) {
+ if (nautilus_directory_is_not_empty (node->data)) {
return TRUE;
}
}
@@ -517,6 +507,12 @@ nautilus_merged_directory_add_real_directory (NautilusMergedDirectory *merged,
real_directory);
}
+GList *
+nautilus_merged_directory_get_real_directories (NautilusMergedDirectory *merged)
+{
+ return g_list_copy (merged->details->directories);
+}
+
static void
merged_callback_remove_directory_cover (gpointer key,
gpointer value,
diff --git a/libnautilus-private/nautilus-merged-directory.h b/libnautilus-private/nautilus-merged-directory.h
index 5a3f41a4d..ac8db0bd5 100644
--- a/libnautilus-private/nautilus-merged-directory.h
+++ b/libnautilus-private/nautilus-merged-directory.h
@@ -61,5 +61,6 @@ void nautilus_merged_directory_add_real_directory (NautilusMergedDirectory
NautilusDirectory *real_directory);
void nautilus_merged_directory_remove_real_directory (NautilusMergedDirectory *merged_directory,
NautilusDirectory *real_directory);
+GList * nautilus_merged_directory_get_real_directories (NautilusMergedDirectory *merged_directory);
#endif /* NAUTILUS_MERGED_DIRECTORY_H */
diff --git a/libnautilus-private/nautilus-trash-file.c b/libnautilus-private/nautilus-trash-file.c
index 7c5e9481f..6eb68aa41 100644
--- a/libnautilus-private/nautilus-trash-file.c
+++ b/libnautilus-private/nautilus-trash-file.c
@@ -26,17 +26,42 @@
#include <config.h>
#include "nautilus-trash-file.h"
+#include "nautilus-directory-notify.h"
+#include "nautilus-file-private.h"
#include "nautilus-file-utilities.h"
+#include "nautilus-glib-extensions.h"
#include "nautilus-gtk-macros.h"
#include "nautilus-trash-directory.h"
#include <gtk/gtksignal.h>
struct NautilusTrashFileDetails {
- NautilusTrashDirectory *as_directory;
+ NautilusTrashDirectory *trash_directory;
+
guint add_directory_connection_id;
guint remove_directory_connection_id;
+
+ GList *files;
+
+ GHashTable *callbacks;
+ GHashTable *monitors;
};
+typedef struct {
+ NautilusTrashFile *trash;
+ NautilusFileCallback callback;
+ gpointer callback_data;
+
+ GList *attributes;
+
+ GList *non_ready_files;
+} TrashCallback;
+
+typedef struct {
+ NautilusTrashFile *trash;
+
+ GList *attributes;
+} TrashMonitor;
+
static void nautilus_trash_file_initialize (gpointer object,
gpointer klass);
static void nautilus_trash_file_initialize_class (gpointer klass);
@@ -45,6 +70,187 @@ NAUTILUS_DEFINE_CLASS_BOILERPLATE (NautilusTrashFile,
nautilus_trash_file,
NAUTILUS_TYPE_FILE)
+static guint
+trash_callback_hash (gconstpointer trash_callback_as_pointer)
+{
+ const TrashCallback *trash_callback;
+
+ trash_callback = trash_callback_as_pointer;
+ return GPOINTER_TO_UINT (trash_callback->callback)
+ ^ GPOINTER_TO_UINT (trash_callback->callback_data);
+}
+
+static gboolean
+trash_callback_equal (gconstpointer trash_callback_as_pointer,
+ gconstpointer trash_callback_as_pointer_2)
+{
+ 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;
+}
+
+static void
+trash_callback_destroy (TrashCallback *trash_callback)
+{
+ g_assert (trash_callback != NULL);
+ g_assert (NAUTILUS_IS_TRASH_FILE (trash_callback->trash));
+
+ nautilus_g_list_free_deep (trash_callback->attributes);
+ g_list_free (trash_callback->non_ready_files);
+ g_free (trash_callback);
+}
+
+static void
+trash_callback_check_done (TrashCallback *trash_callback)
+{
+ /* Check if we are ready. */
+ if (trash_callback->non_ready_files != NULL) {
+ return;
+ }
+
+ /* Remove from the hash table before sending it. */
+ g_hash_table_remove (trash_callback->trash->details->callbacks,
+ trash_callback);
+
+ /* We are ready, so do the real callback. */
+ (* trash_callback->callback) (NAUTILUS_FILE (trash_callback->trash),
+ trash_callback->callback_data);
+
+ /* And we are done. */
+ trash_callback_destroy (trash_callback);
+}
+
+static void
+trash_callback_remove_file (TrashCallback *trash_callback,
+ NautilusFile *file)
+{
+ trash_callback->non_ready_files = g_list_remove
+ (trash_callback->non_ready_files, file);
+ trash_callback_check_done (trash_callback);
+}
+
+static void
+ready_callback (NautilusFile *file,
+ gpointer callback_data)
+{
+ TrashCallback *trash_callback;
+
+ g_assert (NAUTILUS_IS_FILE (file));
+ g_assert (callback_data != NULL);
+
+ trash_callback = callback_data;
+ g_assert (g_list_find (trash_callback->non_ready_files, file) != NULL);
+
+ trash_callback_remove_file (trash_callback, file);
+}
+
+static void
+real_file_changed_callback (NautilusFile *real_file,
+ gpointer callback_data)
+{
+ NautilusTrashFile *trash_file;
+
+ trash_file = NAUTILUS_TRASH_FILE (callback_data);
+ nautilus_file_changed (NAUTILUS_FILE (trash_file));
+}
+
+static void
+monitor_add_file (gpointer key,
+ gpointer value,
+ gpointer callback_data)
+{
+ TrashMonitor *monitor;
+
+ monitor = value;
+ nautilus_file_monitor_add
+ (NAUTILUS_FILE (callback_data),
+ monitor,
+ monitor->attributes);
+}
+
+static void
+add_real_file (NautilusTrashFile *trash,
+ NautilusFile *real_file)
+{
+ g_return_if_fail (NAUTILUS_IS_TRASH_FILE (trash));
+ g_return_if_fail (NAUTILUS_IS_FILE (real_file));
+ g_return_if_fail (!NAUTILUS_IS_TRASH_FILE (real_file));
+ g_return_if_fail (g_list_find (trash->details->files, real_file) == NULL);
+
+ nautilus_file_ref (real_file);
+ trash->details->files = g_list_prepend
+ (trash->details->files, real_file);
+
+ gtk_signal_connect (GTK_OBJECT (real_file),
+ "changed",
+ real_file_changed_callback,
+ trash);
+
+ /* Add the file to any extant monitors. */
+ g_hash_table_foreach (trash->details->monitors,
+ monitor_add_file,
+ real_file);
+}
+
+static void
+trash_callback_remove_file_cover (gpointer key,
+ gpointer value,
+ gpointer callback_data)
+{
+ trash_callback_remove_file
+ (value, NAUTILUS_FILE (callback_data));
+}
+
+static void
+monitor_remove_file (gpointer key,
+ gpointer value,
+ gpointer callback_data)
+{
+ nautilus_file_monitor_remove
+ (NAUTILUS_FILE (callback_data), value);
+}
+
+static void
+remove_real_file (NautilusTrashFile *trash,
+ NautilusFile *real_file)
+{
+ g_return_if_fail (NAUTILUS_IS_TRASH_FILE (trash));
+ g_return_if_fail (NAUTILUS_IS_FILE (real_file));
+ g_return_if_fail (g_list_find (trash->details->files, real_file) != NULL);
+
+ nautilus_g_hash_table_safe_for_each
+ (trash->details->callbacks,
+ trash_callback_remove_file_cover,
+ real_file);
+ g_hash_table_foreach
+ (trash->details->monitors,
+ monitor_remove_file,
+ real_file);
+
+ gtk_signal_disconnect_by_func (GTK_OBJECT (real_file),
+ real_file_changed_callback,
+ trash);
+
+ trash->details->files = g_list_remove
+ (trash->details->files, real_file);
+ nautilus_file_unref (real_file);
+}
+
+static void
+add_real_file_given_directory (NautilusTrashFile *trash_file,
+ NautilusDirectory *real_directory)
+{
+ NautilusFile *real_file;
+
+ real_file = nautilus_directory_get_corresponding_file (real_directory);
+ add_real_file (trash_file, real_file);
+ nautilus_file_unref (real_file);
+}
+
static void
add_directory_callback (NautilusTrashDirectory *trash_directory,
NautilusDirectory *real_directory,
@@ -54,7 +260,11 @@ add_directory_callback (NautilusTrashDirectory *trash_directory,
g_assert (NAUTILUS_IS_DIRECTORY (real_directory));
g_assert (!NAUTILUS_IS_MERGED_DIRECTORY (real_directory));
g_assert (NAUTILUS_IS_TRASH_FILE (trash_file));
- g_assert (trash_file->details->as_directory == trash_directory);
+ g_assert (trash_file->details->trash_directory == trash_directory);
+
+ add_real_file_given_directory (trash_file, real_directory);
+
+ nautilus_file_changed (NAUTILUS_FILE (trash_file));
}
static void
@@ -62,11 +272,324 @@ remove_directory_callback (NautilusTrashDirectory *trash_directory,
NautilusDirectory *real_directory,
NautilusTrashFile *trash_file)
{
+ NautilusFile *real_file;
+
g_assert (NAUTILUS_IS_TRASH_DIRECTORY (trash_directory));
g_assert (NAUTILUS_IS_DIRECTORY (real_directory));
g_assert (!NAUTILUS_IS_MERGED_DIRECTORY (real_directory));
g_assert (NAUTILUS_IS_TRASH_FILE (trash_file));
- g_assert (trash_file->details->as_directory == trash_directory);
+ g_assert (trash_file->details->trash_directory == trash_directory);
+
+ real_file = nautilus_directory_get_corresponding_file (real_directory);
+ remove_real_file (trash_file, real_file);
+ nautilus_file_unref (real_file);
+
+ nautilus_file_changed (NAUTILUS_FILE (trash_file));
+}
+
+static void
+trash_file_call_when_ready (NautilusFile *file,
+ GList *file_attributes,
+ NautilusFileCallback callback,
+ gpointer callback_data)
+
+{
+ NautilusTrashFile *trash;
+ TrashCallback search_key, *trash_callback;
+ GList *node;
+
+ trash = NAUTILUS_TRASH_FILE (file);
+
+ /* 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");
+ 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->attributes = nautilus_g_str_list_copy (file_attributes);
+ for (node = trash->details->files; node != NULL; node = node->next) {
+ trash_callback->non_ready_files = g_list_prepend
+ (trash_callback->non_ready_files, node->data);
+ }
+
+ /* Put it in the hash table. */
+ g_hash_table_insert (trash->details->callbacks,
+ trash_callback, trash_callback);
+
+ /* Handle the pathological case where there are no files. */
+ if (trash->details->files == NULL) {
+ trash_callback_check_done (trash_callback);
+ }
+
+ /* Now connect to each file's call_when_ready. */
+ for (node = trash->details->files; node != NULL; node = node->next) {
+ nautilus_file_call_when_ready
+ (node->data,
+ trash_callback->attributes,
+ ready_callback, trash_callback);
+ }
+}
+
+static void
+trash_file_cancel_call_when_ready (NautilusFile *file,
+ NautilusFileCallback callback,
+ gpointer callback_data)
+{
+ NautilusTrashFile *trash;
+ TrashCallback search_key, *trash_callback;
+ GList *node;
+
+ trash = NAUTILUS_TRASH_FILE (file);
+
+ /* 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) {
+ return;
+ }
+
+ /* Remove from the hash table before working with it. */
+ g_hash_table_remove (trash_callback->trash->details->callbacks, trash_callback);
+
+ /* Tell all the directories to cancel the call. */
+ for (node = trash_callback->non_ready_files; node != NULL; node = node->next) {
+ nautilus_file_cancel_call_when_ready
+ (node->data,
+ ready_callback, trash_callback);
+ }
+ trash_callback_destroy (trash_callback);
+}
+
+static gboolean
+trash_file_check_if_ready (NautilusFile *file,
+ GList *file_attributes)
+{
+ NautilusTrashFile *trash;
+ GList *node;
+
+ trash = NAUTILUS_TRASH_FILE (file);
+
+ for (node = trash->details->files; node != NULL; node = node->next) {
+ if (!nautilus_file_check_if_ready (node->data,
+ file_attributes)) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static void
+trash_file_monitor_add (NautilusFile *file,
+ gconstpointer client,
+ GList *attributes)
+{
+ NautilusTrashFile *trash;
+ TrashMonitor *monitor;
+ GList *node;
+
+ trash = NAUTILUS_TRASH_FILE (file);
+
+ /* Map the client to a unique value so this doesn't interfere
+ * with direct monitoring of the file by the same client.
+ */
+ monitor = g_hash_table_lookup (trash->details->monitors, client);
+ if (monitor != NULL) {
+ g_assert (monitor->trash == trash);
+ nautilus_g_list_free_deep (monitor->attributes);
+ } else {
+ monitor = g_new0 (TrashMonitor, 1);
+ monitor->trash = trash;
+ g_hash_table_insert (trash->details->monitors,
+ (gpointer) client, monitor);
+ }
+ monitor->attributes = nautilus_g_str_list_copy (attributes);
+
+ for (node = trash->details->files; node != NULL; node = node->next) {
+ nautilus_file_monitor_add (node->data, monitor, attributes);
+ }
+}
+
+static void
+trash_file_monitor_remove (NautilusFile *file,
+ gconstpointer client)
+{
+ NautilusTrashFile *trash;
+ TrashMonitor *monitor;
+ GList *node;
+
+ trash = NAUTILUS_TRASH_FILE (file);
+
+ /* Map the client to the value used by the earlier add call. */
+ monitor = g_hash_table_lookup (trash->details->monitors, client);
+ if (monitor == NULL) {
+ return;
+ }
+ g_hash_table_remove (trash->details->monitors, client);
+
+ /* Call through to the real file remove calls. */
+ for (node = trash->details->files; node != NULL; node = node->next) {
+ nautilus_file_monitor_remove (node->data, monitor);
+ }
+
+ nautilus_g_list_free_deep (monitor->attributes);
+ g_free (monitor);
+}
+
+static GnomeVFSFileType
+trash_file_get_file_type (NautilusFile *file)
+{
+ return GNOME_VFS_FILE_TYPE_DIRECTORY;
+}
+
+static gboolean
+trash_file_get_item_count (NautilusFile *file,
+ guint *count,
+ gboolean *count_unreadable)
+{
+ NautilusTrashFile *trash;
+ GList *node;
+ guint one_count, one_unreadable;
+ gboolean got_count;
+
+ trash = NAUTILUS_TRASH_FILE (file);
+
+ got_count = TRUE;
+ if (count != NULL) {
+ *count = 0;
+ }
+ if (count_unreadable != NULL) {
+ *count_unreadable = FALSE;
+ }
+
+ for (node = trash->details->files; node != NULL; node = node->next) {
+ if (!nautilus_file_get_directory_item_count (node->data,
+ &one_count,
+ &one_unreadable)) {
+ got_count = FALSE;
+ }
+
+ if (count != NULL) {
+ *count += one_count;
+ }
+ if (count_unreadable != NULL && one_unreadable) {
+ *count_unreadable = TRUE;
+ }
+ }
+
+ return got_count;
+}
+
+static NautilusRequestStatus
+trash_file_get_deep_counts (NautilusFile *file,
+ guint *directory_count,
+ guint *file_count,
+ guint *unreadable_directory_count,
+ GnomeVFSFileSize *total_size)
+{
+ NautilusTrashFile *trash;
+ GList *node;
+ NautilusRequestStatus status, one_status;
+ guint one_directory_count, one_file_count, one_unreadable_directory_count;
+ GnomeVFSFileSize one_total_size;
+
+ trash = NAUTILUS_TRASH_FILE (file);
+
+ status = NAUTILUS_REQUEST_DONE;
+ if (directory_count != NULL) {
+ *directory_count = 0;
+ }
+ if (file_count != NULL) {
+ *file_count = 0;
+ }
+ if (unreadable_directory_count != NULL) {
+ *unreadable_directory_count = 0;
+ }
+ if (total_size != NULL) {
+ *total_size = 0;
+ }
+
+ for (node = trash->details->files; node != NULL; node = node->next) {
+ one_status = nautilus_file_get_deep_counts
+ (node->data,
+ &one_directory_count,
+ &one_file_count,
+ &one_unreadable_directory_count,
+ &one_total_size);
+
+ if (one_status < status) {
+ status = one_status;
+ }
+ if (directory_count != NULL) {
+ *directory_count += one_directory_count;
+ }
+ if (file_count != NULL) {
+ *file_count += one_file_count;
+ }
+ if (unreadable_directory_count != NULL) {
+ *unreadable_directory_count += one_unreadable_directory_count;
+ }
+ if (total_size != NULL) {
+ *total_size += one_total_size;
+ }
+ }
+
+ return status;
+}
+
+static gboolean
+trash_file_get_date (NautilusFile *file,
+ NautilusDateType date_type,
+ time_t *date)
+{
+ NautilusTrashFile *trash;
+ GList *node;
+ gboolean got_at_least_one;
+ gboolean got_all;
+ time_t one_date;
+
+ trash = NAUTILUS_TRASH_FILE (file);
+
+ got_at_least_one = FALSE;
+ got_all = TRUE;
+
+ for (node = trash->details->files; node != NULL; node = node->next) {
+ if (nautilus_file_get_date (node->data,
+ date_type,
+ &one_date)) {
+ if (!got_at_least_one) {
+ got_at_least_one = TRUE;
+ if (date != NULL) {
+ *date = one_date;
+ }
+ } else {
+ if (date != NULL && one_date > *date) {
+ *date = one_date;
+ }
+ }
+ } else {
+ got_all = FALSE;
+ }
+ }
+
+ return got_at_least_one && got_all;
+}
+
+
+static void
+remove_all_real_files (NautilusTrashFile *trash)
+{
+ while (trash->details->files != NULL) {
+ remove_real_file (trash, trash->details->files->data);
+ }
}
static void
@@ -74,13 +597,18 @@ nautilus_trash_file_initialize (gpointer object, gpointer klass)
{
NautilusTrashFile *trash_file;
NautilusTrashDirectory *trash_directory;
+ GList *real_directories, *node;
trash_file = NAUTILUS_TRASH_FILE (object);
trash_directory = NAUTILUS_TRASH_DIRECTORY (nautilus_directory_get (NAUTILUS_TRASH_URI));
trash_file->details = g_new0 (NautilusTrashFileDetails, 1);
- trash_file->details->as_directory = trash_directory;
+ trash_file->details->trash_directory = trash_directory;
+
+ trash_file->details->callbacks = g_hash_table_new
+ (trash_callback_hash, trash_callback_equal);
+ trash_file->details->monitors = g_hash_table_new (NULL, NULL);
trash_file->details->add_directory_connection_id = gtk_signal_connect
(GTK_OBJECT (trash_directory),
@@ -92,6 +620,13 @@ nautilus_trash_file_initialize (gpointer object, gpointer klass)
"remove_real_directory",
remove_directory_callback,
trash_file);
+
+ real_directories = nautilus_merged_directory_get_real_directories
+ (NAUTILUS_MERGED_DIRECTORY (trash_directory));
+ for (node = real_directories; node != NULL; node = node->next) {
+ add_real_file_given_directory (trash_file, node->data);
+ }
+ g_list_free (real_directories);
}
static void
@@ -101,15 +636,29 @@ trash_destroy (GtkObject *object)
NautilusTrashDirectory *trash_directory;
trash_file = NAUTILUS_TRASH_FILE (object);
- trash_directory = trash_file->details->as_directory;
+ trash_directory = trash_file->details->trash_directory;
+
+ remove_all_real_files (trash_file);
+
+ if (g_hash_table_size (trash_file->details->callbacks) != 0) {
+ g_warning ("call_when_ready still pending when trash virtual file is destroyed");
+ }
+ if (g_hash_table_size (trash_file->details->monitors) != 0) {
+ g_warning ("file monitor still active when trash virtual file is destroyed");
+ }
gtk_signal_disconnect (GTK_OBJECT (trash_directory),
trash_file->details->add_directory_connection_id);
gtk_signal_disconnect (GTK_OBJECT (trash_directory),
trash_file->details->remove_directory_connection_id);
- nautilus_directory_unref (NAUTILUS_DIRECTORY (trash_directory));
+
+ g_hash_table_destroy (trash_file->details->callbacks);
+ g_hash_table_destroy (trash_file->details->monitors);
+
g_free (trash_file->details);
+ nautilus_directory_unref (NAUTILUS_DIRECTORY (trash_directory));
+
NAUTILUS_CALL_PARENT_CLASS (GTK_OBJECT_CLASS, destroy, (object));
}
@@ -124,5 +673,13 @@ nautilus_trash_file_initialize_class (gpointer klass)
object_class->destroy = trash_destroy;
- /* file_class-> */
+ file_class->monitor_add = trash_file_monitor_add;
+ file_class->monitor_remove = trash_file_monitor_remove;
+ file_class->call_when_ready = trash_file_call_when_ready;
+ file_class->cancel_call_when_ready = trash_file_cancel_call_when_ready;
+ file_class->check_if_ready = trash_file_check_if_ready;
+ file_class->get_file_type = trash_file_get_file_type;
+ file_class->get_item_count = trash_file_get_item_count;
+ file_class->get_deep_counts = trash_file_get_deep_counts;
+ file_class->get_date = trash_file_get_date;
}
diff --git a/libnautilus-private/nautilus-vfs-file.c b/libnautilus-private/nautilus-vfs-file.c
index 455ac59c7..eba08921b 100644
--- a/libnautilus-private/nautilus-vfs-file.c
+++ b/libnautilus-private/nautilus-vfs-file.c
@@ -94,6 +94,13 @@ vfs_file_check_if_ready (NautilusFile *file,
file_attributes);
}
+static GnomeVFSFileType
+vfs_file_get_file_type (NautilusFile *file)
+{
+ return nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_TYPE)
+ ? GNOME_VFS_FILE_TYPE_UNKNOWN : file->details->info->type;
+}
+
static gboolean
vfs_file_get_item_count (NautilusFile *file,
guint *count,
@@ -103,10 +110,14 @@ vfs_file_get_item_count (NautilusFile *file,
*count_unreadable = file->details->directory_count_failed;
}
if (!file->details->got_directory_count) {
- *count = 0;
+ if (count != NULL) {
+ *count = 0;
+ }
return FALSE;
}
- *count = file->details->directory_count;
+ if (count != NULL) {
+ *count = file->details->directory_count;
+ }
return TRUE;
}
@@ -163,6 +174,61 @@ vfs_file_get_deep_counts (NautilusFile *file,
return NAUTILUS_REQUEST_DONE;
}
+static gboolean
+vfs_file_get_date (NautilusFile *file,
+ NautilusDateType date_type,
+ time_t *date)
+{
+ switch (date_type) {
+ case NAUTILUS_DATE_TYPE_CHANGED:
+ /* Before we have info on a file, the date is unknown. */
+ if (nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_CTIME)) {
+ return FALSE;
+ }
+ if (date != NULL) {
+ *date = file->details->info->ctime;
+ }
+ return TRUE;
+ case NAUTILUS_DATE_TYPE_ACCESSED:
+ /* Before we have info on a file, the date is unknown. */
+ if (nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_ATIME)) {
+ return FALSE;
+ }
+ if (date != NULL) {
+ *date = file->details->info->atime;
+ }
+ return TRUE;
+ case NAUTILUS_DATE_TYPE_MODIFIED:
+ /* Before we have info on a file, the date is unknown. */
+ if (nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_MTIME)) {
+ return FALSE;
+ }
+ if (date != NULL) {
+ *date = file->details->info->mtime;
+ }
+ return TRUE;
+ case NAUTILUS_DATE_TYPE_PERMISSIONS_CHANGED:
+ /* Before we have info on a file, the date is unknown. */
+ if (nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_MTIME) ||
+ nautilus_file_info_missing (file, GNOME_VFS_FILE_INFO_FIELDS_CTIME)) {
+ return FALSE;
+ }
+ /* mtime is when the contents changed; ctime is when the
+ * contents or the permissions (inc. owner/group) changed.
+ * So we can only know when the permissions changed if mtime
+ * and ctime are different.
+ */
+ if (file->details->info->mtime == file->details->info->ctime) {
+ return FALSE;
+ }
+ if (date != NULL) {
+ *date = file->details->info->ctime;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
static void
nautilus_vfs_file_initialize (gpointer object, gpointer klass)
{
@@ -195,6 +261,8 @@ nautilus_vfs_file_initialize_class (gpointer klass)
file_class->call_when_ready = vfs_file_call_when_ready;
file_class->cancel_call_when_ready = vfs_file_cancel_call_when_ready;
file_class->check_if_ready = vfs_file_check_if_ready;
+ file_class->get_file_type = vfs_file_get_file_type;
file_class->get_item_count = vfs_file_get_item_count;
file_class->get_deep_counts = vfs_file_get_deep_counts;
+ file_class->get_date = vfs_file_get_date;
}
diff --git a/libnautilus-private/nautilus-view-identifier.c b/libnautilus-private/nautilus-view-identifier.c
index f80fc92e4..6209bd452 100644
--- a/libnautilus-private/nautilus-view-identifier.c
+++ b/libnautilus-private/nautilus-view-identifier.c
@@ -55,8 +55,8 @@ nautilus_view_identifier_copy (NautilusViewIdentifier *identifier)
return nautilus_view_identifier_new (identifier->iid, identifier->name);
}
-/* Returns a list of languages (with one element), containing
- the LANG or LANGUAGE environment setting.
+/* Returns a list of languages, containing
+ the LANG or LANGUAGE environment setting (with and without region code).
The elements in the returned list must be freed */
static GSList *
get_lang_list (void)
@@ -96,8 +96,9 @@ get_lang_list (void)
lang string */
if (!nautilus_str_is_empty (lang_with_locale)) {
retval = g_slist_prepend (retval,
- lang_with_locale);
+ g_strdup (lang_with_locale));
}
+ g_free (lang_with_locale);
if (!nautilus_str_is_empty (lang)) {
retval = g_slist_prepend (retval, g_strdup (lang));
}
diff --git a/libnautilus/nautilus-view-component.idl b/libnautilus/nautilus-view-component.idl
index 46680cd86..3a213c7ca 100644
--- a/libnautilus/nautilus-view-component.idl
+++ b/libnautilus/nautilus-view-component.idl
@@ -39,11 +39,6 @@
#include <Bonobo.idl>
-/* FIXME bugzilla.eazel.com 2974: Use of doubles causes alignment
- * problems in Solaris due to an ORBit bug; we use floats throughout
- * this file as a workaround.
- */
-
module Nautilus {
/* URIs are just plain strings, but we use a typedef to make
diff --git a/po/POTFILES.ignore b/po/POTFILES.ignore
deleted file mode 100644
index 6706fc8cc..000000000
--- a/po/POTFILES.ignore
+++ /dev/null
@@ -1 +0,0 @@
-test/test-nautilus-widgets.c
diff --git a/src/file-manager/fm-desktop-icon-view.c b/src/file-manager/fm-desktop-icon-view.c
index 19796763b..2c15eb3f0 100644
--- a/src/file-manager/fm-desktop-icon-view.c
+++ b/src/file-manager/fm-desktop-icon-view.c
@@ -797,7 +797,10 @@ update_home_link_and_delete_copies (void)
/* Note to translators: If it's hard to compose a good home
* icon name from the user name, you can use a string without
* an "%s" here, in which case the home icon name will not
- * include the user's name, which should be fine.
+ * include the user's name, which should be fine. To avoid a
+ * warning, put "%.0s" somewhere in the string, which will
+ * match the user name string passed by the C code, but not
+ * put the user name in the final string.
*/
home_link_name = g_strdup_printf (_("%s's Home"), g_get_user_name ());
diff --git a/src/file-manager/fm-properties-window.c b/src/file-manager/fm-properties-window.c
index 8bd21f5de..0bcb07f9a 100644
--- a/src/file-manager/fm-properties-window.c
+++ b/src/file-manager/fm-properties-window.c
@@ -99,21 +99,25 @@ enum {
#define ERASE_EMBLEM_FILENAME "erase.png"
#define EMBLEM_COLUMN_COUNT 2
-static void real_destroy (GtkObject *object);
-static void real_finalize (GtkObject *object);
-static void real_shutdown (GtkObject *object);
-static void fm_properties_window_initialize_class (FMPropertiesWindowClass *class);
-static void fm_properties_window_initialize (FMPropertiesWindow *window);
-static void create_properties_window_callback (NautilusFile *file,
- gpointer data);
-static void cancel_group_change_callback (gpointer callback_data);
-static void cancel_owner_change_callback (gpointer callback_data);
-static void directory_view_destroyed_callback (FMDirectoryView *view,
- gpointer callback_data);
-static void select_image_button_callback (GtkWidget *widget,
- NautilusFile *file);
-static void remove_image_button_callback (GtkWidget *widget,
- NautilusFile *file);
+static void real_destroy (GtkObject *object);
+static void real_finalize (GtkObject *object);
+static void real_shutdown (GtkObject *object);
+static void fm_properties_window_initialize_class (FMPropertiesWindowClass *class);
+static void fm_properties_window_initialize (FMPropertiesWindow *window);
+static void create_properties_window_callback (NautilusFile *file,
+ gpointer data);
+static void cancel_group_change_callback (gpointer callback_data);
+static void cancel_owner_change_callback (gpointer callback_data);
+static void directory_view_destroyed_callback (FMDirectoryView *view,
+ gpointer callback_data);
+static void select_image_button_callback (GtkWidget *widget,
+ NautilusFile *file);
+static void remove_image_button_callback (GtkWidget *widget,
+ NautilusFile *file);
+static void remove_pending_file (NautilusFile *file,
+ gboolean cancel_call_when_ready,
+ gboolean cancel_timed_wait,
+ gboolean cancel_destroy_handler);
NAUTILUS_DEFINE_CLASS_BOILERPLATE (FMPropertiesWindow, fm_properties_window, GTK_TYPE_WINDOW)
@@ -1831,10 +1835,8 @@ create_properties_window (NautilusFile *file)
GList *attributes;
window = FM_PROPERTIES_WINDOW (gtk_widget_new (fm_properties_window_get_type (), NULL));
- /* Note that we've already reffed file in get_and_ref_file_for_display,
- * both for our use here and for the windows hash table. It gets unreffed
- * in real_destroy.
- */
+
+ nautilus_file_ref (file);
window->details->file = file;
gtk_container_set_border_width (GTK_CONTAINER (window), GNOME_PAD);
@@ -1928,68 +1930,63 @@ get_and_ref_file_to_display (NautilusFile *file)
}
static void
-cancel_create_properties_window_callback (gpointer callback_data)
-{
- NautilusFile *file;
- FMDirectoryView *view;
-
- file = NAUTILUS_FILE (callback_data);
- view = g_hash_table_lookup (pending_files, file);
- g_assert (view != NULL);
-
- nautilus_file_cancel_call_when_ready (file, create_properties_window_callback, view);
- g_hash_table_remove (pending_files, file);
- nautilus_file_unref (file);
-}
-
-static void
-remove_pending_file (NautilusFile *file)
-{
- g_hash_table_remove (pending_files, file);
- nautilus_timed_wait_stop (cancel_create_properties_window_callback, file);
-}
-
-static void
-pending_file_succeeded (NautilusFile *file)
-{
- FMDirectoryView *view;
-
- view = g_hash_table_lookup (pending_files, file);
- gtk_signal_disconnect_by_func (GTK_OBJECT (view),
- directory_view_destroyed_callback,
- file);
- remove_pending_file (file);
-
-}
-
-static void
-create_properties_window_callback (NautilusFile *file, gpointer data)
+create_properties_window_callback (NautilusFile *file, gpointer callback_data)
{
FMPropertiesWindow *new_window;
- g_assert (FM_IS_DIRECTORY_VIEW (data));
-
- pending_file_succeeded (file);
+ g_assert (FM_IS_DIRECTORY_VIEW (callback_data));
new_window = create_properties_window (file);
+
+ remove_pending_file (file, FALSE, TRUE, TRUE);
+
g_hash_table_insert (windows, file, new_window);
/* FIXME bugzilla.eazel.com 2151:
* See comment elsewhere in this file about bug 2151.
*/
#ifdef UNDO_ENABLED
- nautilus_undo_share_undo_manager (GTK_OBJECT (new_window), GTK_OBJECT (data));
+ nautilus_undo_share_undo_manager (GTK_OBJECT (new_window),
+ GTK_OBJECT (callback_data));
#endif
nautilus_gtk_window_present (GTK_WINDOW (new_window));
}
static void
+cancel_create_properties_window_callback (gpointer callback_data)
+{
+ remove_pending_file (NAUTILUS_FILE (callback_data), TRUE, FALSE, TRUE);
+}
+
+static void
directory_view_destroyed_callback (FMDirectoryView *view, gpointer callback_data)
{
- NautilusFile *file;
+ remove_pending_file (NAUTILUS_FILE (callback_data), TRUE, TRUE, FALSE);
+}
- file = NAUTILUS_FILE (callback_data);
- remove_pending_file (file);
+static void
+remove_pending_file (NautilusFile *file,
+ gboolean cancel_call_when_ready,
+ gboolean cancel_timed_wait,
+ gboolean cancel_destroy_handler)
+{
+ FMDirectoryView *view;
+
+ view = g_hash_table_lookup (pending_files, file);
+ g_return_if_fail (view != NULL);
+
+ if (cancel_call_when_ready) {
+ nautilus_file_cancel_call_when_ready (file, create_properties_window_callback, view);
+ }
+ if (cancel_timed_wait) {
+ nautilus_timed_wait_stop (cancel_create_properties_window_callback, file);
+ }
+ if (cancel_destroy_handler) {
+ gtk_signal_disconnect_by_func (GTK_OBJECT (view),
+ directory_view_destroyed_callback,
+ file);
+ }
+ g_hash_table_remove (pending_files, file);
nautilus_file_unref (file);
}
diff --git a/src/file-manager/nautilus-desktop-icon-view-ui.xml b/src/file-manager/nautilus-desktop-icon-view-ui.xml
index 3eda22462..40f019d9c 100644
--- a/src/file-manager/nautilus-desktop-icon-view-ui.xml
+++ b/src/file-manager/nautilus-desktop-icon-view-ui.xml
@@ -36,7 +36,7 @@
<menuitem name="New Terminal" verb="New Terminal"/>
</placeholder>
<placeholder name="Volume Items" delimit="top">
- <submenu name="Disks"
+ <submenu name="Disks" tearoff="0"
_label="Disks"
_tip="Mount or unmount disks"/>
</placeholder>
diff --git a/src/nautilus-application.c b/src/nautilus-application.c
index ed47bde54..02b9101e9 100644
--- a/src/nautilus-application.c
+++ b/src/nautilus-application.c
@@ -478,7 +478,14 @@ nautilus_application_startup (NautilusApplication *application,
}
/* We're done with the shell now, so let it go. */
- bonobo_object_release_unref (shell, &ev);
+ /* HACK: Don't bother releasing the shell in the case where we
+ * just told it to quit -- that just leads to hangs and does
+ * no good. We could probably fix this in some fancier way if
+ * we could figure out a better lifetime rule.
+ */
+ if (!kill_shell) {
+ bonobo_object_release_unref (shell, &ev);
+ }
out:
CORBA_exception_free (&ev);
diff --git a/src/nautilus-shell-interface.idl b/src/nautilus-shell-interface.idl
index 1856fd9b7..85df1c03f 100644
--- a/src/nautilus-shell-interface.idl
+++ b/src/nautilus-shell-interface.idl
@@ -9,12 +9,12 @@
module Nautilus {
interface Shell : ::Bonobo::Unknown {
- oneway void open_windows (in URIList uris, in string geometry);
- oneway void open_default_window (in string geometry);
- oneway void start_desktop ();
- oneway void stop_desktop ();
- oneway void quit ();
- oneway void restart ();
+ void open_windows (in URIList uris, in string geometry);
+ void open_default_window (in string geometry);
+ void start_desktop ();
+ void stop_desktop ();
+ void quit ();
+ void restart ();
};
};
diff --git a/src/nautilus-window-manage-views.c b/src/nautilus-window-manage-views.c
index 3706adb8c..b26e04ba7 100644
--- a/src/nautilus-window-manage-views.c
+++ b/src/nautilus-window-manage-views.c
@@ -578,7 +578,6 @@ ref_now_unref_at_idle_time (GtkObject *object)
g_idle_add (unref_callback, object);
}
-
/* This is called when we have decided we can actually change to the new view/location situation. */
static void
location_has_really_changed (NautilusWindow *window)