1
0
mirror of https://gitlab.gnome.org/GNOME/nautilus synced 2024-06-30 23:46:35 +00:00

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.
This commit is contained in:
Darin Adler 2001-01-18 19:26:03 +00:00
parent aee3945efe
commit e82bab8c49
31 changed files with 1801 additions and 437 deletions

118
ChangeLog
View File

@ -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:

View File

@ -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.

View File

@ -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);

View File

@ -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);

View File

@ -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_unreadable != NULL) {
*count_unreadable = 0;
if (count != NULL) {
*count = 0;
}
if (count_unreadable != NULL) {
*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;
}

View File

@ -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 */

View File

@ -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:

View File

@ -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,

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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));
}

View File

@ -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.

View File

@ -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);

View File

@ -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);

View File

@ -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_unreadable != NULL) {
*count_unreadable = 0;
if (count != NULL) {
*count = 0;
}
if (count_unreadable != NULL) {
*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;
}

View File

@ -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 */

View File

@ -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:

View File

@ -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,

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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));
}

View File

@ -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

View File

@ -1 +0,0 @@
test/test-nautilus-widgets.c

View File

@ -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 ());

View File

@ -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);
}

View File

@ -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>

View File

@ -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);

View File

@ -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 ();
};
};

View File

@ -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)