Nautilus used to handle all the error handling in its asynchronous gnome_vfs_async_xfer callback, but it is not guaranteed to be always called, so problems may remain unhandled and cause data loss ([1]). [2] has some details. This patch still needs some serious testing. [1] http://bugzilla.gnome.org/show_bug.cgi?id=144726 [2] http://blogs.gnome.org/edit/cneumair/2006/01/10 -- Christian Neumair <chris gnome-de org>
Index: libnautilus-private/nautilus-file-operations.c
===================================================================
RCS file: /cvs/gnome/nautilus/libnautilus-private/nautilus-file-operations.c,v
retrieving revision 1.203
diff -u -p -r1.203 nautilus-file-operations.c
--- libnautilus-private/nautilus-file-operations.c 18 Dec 2005 01:21:18 -0000 1.203
+++ libnautilus-private/nautilus-file-operations.c 10 Jan 2006 20:26:33 -0000
@@ -59,24 +59,28 @@
#include "nautilus-link.h"
#include "nautilus-trash-monitor.h"
-typedef enum TransferKind TransferKind;
-typedef struct TransferInfo TransferInfo;
+typedef enum OperationKind OperationKind;
+typedef struct OperationInfo OperationInfo;
typedef struct IconPositionIterator IconPositionIterator;
-enum TransferKind {
+static void icon_position_iterator_free (IconPositionIterator *position_iterator);
+
+enum OperationKind {
TRANSFER_MOVE,
TRANSFER_COPY,
TRANSFER_DUPLICATE,
TRANSFER_MOVE_TO_TRASH,
TRANSFER_EMPTY_TRASH,
TRANSFER_DELETE,
- TRANSFER_LINK
+ TRANSFER_LINK,
+ CREATE_FOLDER,
+ CREATE_FILE
};
/* Copy engine callback state */
-struct TransferInfo {
+struct OperationInfo {
+ /* basic info */
GnomeVFSAsyncHandle *handle;
- NautilusFileOperationsProgress *progress_dialog;
const char *operation_title; /* "Copying files" */
const char *action_label; /* "Files copied:" */
const char *progress_verb; /* "Copying" */
@@ -85,41 +89,47 @@ struct TransferInfo {
GnomeVFSXferErrorMode error_mode;
GnomeVFSXferOverwriteMode overwrite_mode;
GtkWidget *parent_view;
- TransferKind kind;
- void (* done_callback) (GHashTable *debuting_uris, gpointer data);
- gpointer done_callback_data;
+ OperationKind kind;
+ void (* done_callback) (GHashTable *debuting_uris, gpointer user_data);
+ gpointer done_callback_user_data;
GHashTable *debuting_uris;
gboolean cancelled;
+ NautilusFileOperationsProgress *progress_dialog;
IconPositionIterator *iterator;
+ int last_sync_response;
};
-static TransferInfo *
-transfer_info_new (GtkWidget *parent_view)
+static OperationInfo *
+operation_info_new (GtkWidget *parent_view)
{
- TransferInfo *result;
-
- result = g_new0 (TransferInfo, 1);
+ OperationInfo *result;
+
+ result = g_new0 (OperationInfo, 1);
result->parent_view = parent_view;
-
+ result->debuting_uris = g_hash_table_new_full
+ (g_str_hash, g_str_equal, g_free, NULL);
+
eel_add_weak_pointer (&result->parent_view);
return result;
}
static void
-transfer_info_destroy (TransferInfo *transfer_info)
+operation_info_destroy (OperationInfo *operation_info)
{
- eel_remove_weak_pointer (&transfer_info->parent_view);
-
- if (transfer_info->progress_dialog != NULL) {
- nautilus_file_operations_progress_done (transfer_info->progress_dialog);
+ eel_remove_weak_pointer (&operation_info->parent_view);
+
+ icon_position_iterator_free (operation_info->iterator);
+
+ if (operation_info->progress_dialog != NULL) {
+ nautilus_file_operations_progress_done (operation_info->progress_dialog);
}
- if (transfer_info->debuting_uris != NULL) {
- g_hash_table_destroy (transfer_info->debuting_uris);
+ if (operation_info->debuting_uris != NULL) {
+ g_hash_table_destroy (operation_info->debuting_uris);
}
- g_free (transfer_info);
+ g_free (operation_info);
}
/* Struct used to control applying icon positions to
@@ -347,58 +357,58 @@ extract_and_ellipsize_file_name_for_dial
}
static GtkWidget *
-parent_for_error_dialog (TransferInfo *transfer_info)
+parent_for_error_dialog (OperationInfo *operation_info)
{
- if (transfer_info->progress_dialog != NULL) {
- return GTK_WIDGET (transfer_info->progress_dialog);
+ if (operation_info->progress_dialog != NULL) {
+ return GTK_WIDGET (operation_info->progress_dialog);
}
- return transfer_info->parent_view;
+ return operation_info->parent_view;
}
static void
-handle_response_callback (GtkDialog *dialog, int response, TransferInfo *transfer_info)
+handle_response_callback (GtkDialog *dialog, int response, OperationInfo *operation_info)
{
- transfer_info->cancelled = TRUE;
+ operation_info->cancelled = TRUE;
}
static void
-handle_close_callback (GtkDialog *dialog, TransferInfo *transfer_info)
+handle_close_callback (GtkDialog *dialog, OperationInfo *operation_info)
{
- transfer_info->cancelled = TRUE;
+ operation_info->cancelled = TRUE;
}
static void
-create_transfer_dialog (const GnomeVFSXferProgressInfo *progress_info,
- TransferInfo *transfer_info)
+create_operation_dialog (const GnomeVFSXferProgressInfo *progress_info,
+ OperationInfo *operation_info)
{
- g_return_if_fail (transfer_info->progress_dialog == NULL);
+ g_return_if_fail (operation_info->progress_dialog == NULL);
- transfer_info->progress_dialog = nautilus_file_operations_progress_new
- (transfer_info->operation_title, "", "", "", 0, 0, TRUE);
+ operation_info->progress_dialog = nautilus_file_operations_progress_new
+ (operation_info->operation_title, "", "", "", 0, 0, TRUE);
/* Treat clicking on the close box or use of the escape key
* the same as clicking cancel.
*/
- g_signal_connect (transfer_info->progress_dialog,
+ g_signal_connect (operation_info->progress_dialog,
"response",
G_CALLBACK (handle_response_callback),
- transfer_info);
- g_signal_connect (transfer_info->progress_dialog,
+ operation_info);
+ g_signal_connect (operation_info->progress_dialog,
"close",
G_CALLBACK (handle_close_callback),
- transfer_info);
+ operation_info);
/* Make the progress dialog show up over the window we are copying into */
- if (transfer_info->parent_view != NULL) {
+ if (operation_info->parent_view != NULL) {
GtkWidget *toplevel;
/* Transient-for-desktop are visible on all desktops, we don't want
that. */
- toplevel = gtk_widget_get_toplevel (transfer_info->parent_view);
+ toplevel = gtk_widget_get_toplevel (operation_info->parent_view);
if (toplevel != NULL &&
g_object_get_data (G_OBJECT (toplevel), "is_desktop_window") == NULL) {
- gtk_window_set_transient_for (GTK_WINDOW (transfer_info->progress_dialog),
+ gtk_window_set_transient_for (GTK_WINDOW (operation_info->progress_dialog),
GTK_WINDOW (toplevel));
}
}
@@ -491,123 +501,91 @@ progress_dialog_set_to_from_item_text (N
g_free (to_text);
}
-static int
-handle_transfer_ok (const GnomeVFSXferProgressInfo *progress_info,
- TransferInfo *transfer_info)
+static void
+update_progress_dialog (const GnomeVFSXferProgressInfo *progress_info,
+ OperationInfo *operation_info)
{
- if (transfer_info->cancelled
- && progress_info->phase != GNOME_VFS_XFER_PHASE_COMPLETED) {
- /* If cancelled, delete any partially copied files that are laying
- * around and return. Don't delete the source though..
- */
- if (progress_info->target_name != NULL
- && progress_info->source_name != NULL
- && strcmp (progress_info->source_name, progress_info->target_name) != 0
- && progress_info->bytes_total != progress_info->bytes_copied) {
- GList *delete_me;
-
- delete_me = g_list_prepend (NULL, progress_info->target_name);
- nautilus_file_operations_delete (delete_me, transfer_info->parent_view);
- g_list_free (delete_me);
- }
-
- return 0;
- }
-
switch (progress_info->phase) {
case GNOME_VFS_XFER_PHASE_INITIAL:
- create_transfer_dialog (progress_info, transfer_info);
- return 1;
+ break;
case GNOME_VFS_XFER_PHASE_COLLECTING:
- if (transfer_info->progress_dialog != NULL) {
+ if (operation_info->progress_dialog != NULL) {
nautilus_file_operations_progress_set_operation_string
- (transfer_info->progress_dialog,
- transfer_info->preparation_name);
+ (operation_info->progress_dialog,
+ operation_info->preparation_name);
}
- return 1;
+ break;
case GNOME_VFS_XFER_PHASE_READYTOGO:
- if (transfer_info->progress_dialog != NULL) {
+ if (operation_info->progress_dialog != NULL) {
nautilus_file_operations_progress_set_operation_string
- (transfer_info->progress_dialog,
- transfer_info->action_label);
+ (operation_info->progress_dialog,
+ operation_info->action_label);
nautilus_file_operations_progress_set_total
- (transfer_info->progress_dialog,
+ (operation_info->progress_dialog,
progress_info->files_total,
progress_info->bytes_total);
}
- return 1;
-
+ break;
+
case GNOME_VFS_XFER_PHASE_DELETESOURCE:
- nautilus_file_changes_consume_changes (FALSE);
- if (transfer_info->progress_dialog != NULL) {
+ if (operation_info->progress_dialog != NULL) {
progress_dialog_set_to_from_item_text
- (transfer_info->progress_dialog,
- transfer_info->progress_verb,
+ (operation_info->progress_dialog,
+ operation_info->progress_verb,
progress_info->source_name,
NULL,
progress_info->file_index,
progress_info->file_size);
nautilus_file_operations_progress_update_sizes
- (transfer_info->progress_dialog,
+ (operation_info->progress_dialog,
MIN (progress_info->bytes_copied,
progress_info->bytes_total),
MIN (progress_info->total_bytes_copied,
progress_info->bytes_total));
}
- return 1;
+ break;
case GNOME_VFS_XFER_PHASE_MOVING:
case GNOME_VFS_XFER_PHASE_OPENSOURCE:
case GNOME_VFS_XFER_PHASE_OPENTARGET:
/* fall through */
case GNOME_VFS_XFER_PHASE_COPYING:
- if (transfer_info->progress_dialog != NULL) {
+ if (operation_info->progress_dialog != NULL) {
if (progress_info->bytes_copied == 0) {
progress_dialog_set_to_from_item_text
- (transfer_info->progress_dialog,
- transfer_info->progress_verb,
+ (operation_info->progress_dialog,
+ operation_info->progress_verb,
progress_info->source_name,
progress_info->target_name,
progress_info->file_index,
progress_info->file_size);
} else {
nautilus_file_operations_progress_update_sizes
- (transfer_info->progress_dialog,
+ (operation_info->progress_dialog,
MIN (progress_info->bytes_copied,
progress_info->bytes_total),
MIN (progress_info->total_bytes_copied,
progress_info->bytes_total));
}
}
- return 1;
+ break;
case GNOME_VFS_XFER_PHASE_CLEANUP:
- if (transfer_info->progress_dialog != NULL) {
+ if (operation_info->progress_dialog != NULL) {
nautilus_file_operations_progress_clear
- (transfer_info->progress_dialog);
+ (operation_info->progress_dialog);
nautilus_file_operations_progress_set_operation_string
- (transfer_info->progress_dialog,
- transfer_info->cleanup_name);
+ (operation_info->progress_dialog,
+ operation_info->cleanup_name);
}
- return 1;
+ break;
case GNOME_VFS_XFER_PHASE_COMPLETED:
- nautilus_file_changes_consume_changes (TRUE);
- if (transfer_info->done_callback != NULL) {
- transfer_info->done_callback (transfer_info->debuting_uris,
- transfer_info->done_callback_data);
- /* done_callback now owns (will free) debuting_uris */
- transfer_info->debuting_uris = NULL;
- }
-
- transfer_info_destroy (transfer_info);
- return 1;
-
default:
- return 1;
+ break;
}
}
@@ -632,7 +610,7 @@ typedef enum {
static void
build_error_string (const char *source_name, const char *target_name,
- TransferKind operation_kind,
+ OperationKind operation_kind,
NautilusFileOperationsErrorKind error_kind,
NautilusFileOperationsErrorLocation error_location,
GnomeVFSResult error,
@@ -687,6 +665,25 @@ build_error_string (const char *source_n
}
break;
+ case CREATE_FILE:
+ case CREATE_FOLDER:
+ switch (error) {
+ *error_string = g_strdup_printf (_("Error While Creating \"%s\"."), target_name);
+
+ case GNOME_VFS_ERROR_ACCESS_DENIED:
+ detail_format = _("You do not have permissions to write to the destination.");
+ break;
+
+ case GNOME_VFS_ERROR_NO_SPACE:
+ detail_format = _("There is no space on the destination.");
+ break;
+
+ default:
+ detail_format = (char *) gnome_vfs_result_to_string (error);
+ break;
+ }
+ break;
+
default:
g_assert_not_reached ();
break;
@@ -900,11 +897,11 @@ build_error_string (const char *source_n
}
static int
-handle_transfer_vfs_error (const GnomeVFSXferProgressInfo *progress_info,
- TransferInfo *transfer_info)
+handle_operation_vfs_error (const GnomeVFSXferProgressInfo *progress_info,
+ OperationInfo *operation_info)
{
- /* Notice that the error mode in `transfer_info' is the one we have been
- * requested, but the transfer is always performed in mode
+ /* Notice that the error mode in `operation_info' is the one we have been
+ * requested, but the operation is always performed in mode
* `GNOME_VFS_XFER_ERROR_MODE_QUERY'.
*/
@@ -917,26 +914,28 @@ handle_transfer_vfs_error (const GnomeVF
NautilusFileOperationsErrorKind error_kind;
NautilusFileOperationsErrorLocation error_location;
- switch (transfer_info->error_mode) {
+ switch (operation_info->error_mode) {
case GNOME_VFS_XFER_ERROR_MODE_QUERY:
- /* transfer error, prompt the user to continue or cancel */
+ /* operation error, prompt the user to continue or cancel */
/* stop timeout while waiting for user */
- nautilus_file_operations_progress_pause_timeout (transfer_info->progress_dialog);
+ if (operation_info->progress_dialog != NULL) {
+ nautilus_file_operations_progress_pause_timeout (operation_info->progress_dialog);
+ }
formatted_source_name = NULL;
formatted_target_name = NULL;
if (progress_info->source_name != NULL) {
formatted_source_name = format_and_ellipsize_uri_for_dialog
- (parent_for_error_dialog (transfer_info),
+ (parent_for_error_dialog (operation_info),
progress_info->source_name);
}
if (progress_info->target_name != NULL) {
formatted_target_name = format_and_ellipsize_uri_for_dialog
- (parent_for_error_dialog (transfer_info),
+ (parent_for_error_dialog (operation_info),
progress_info->target_name);
}
@@ -948,36 +947,36 @@ handle_transfer_vfs_error (const GnomeVF
*/
if ((progress_info->vfs_status == GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM
|| progress_info->vfs_status == GNOME_VFS_ERROR_READ_ONLY)
- && (transfer_info->kind == TRANSFER_DELETE
- || transfer_info->kind == TRANSFER_EMPTY_TRASH)) {
+ && (operation_info->kind == TRANSFER_DELETE
+ || operation_info->kind == TRANSFER_EMPTY_TRASH)) {
error_location = ERROR_LOCATION_SOURCE_PARENT;
error_kind = ERROR_READ_ONLY;
} else if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED
- && (transfer_info->kind == TRANSFER_DELETE
- || transfer_info->kind == TRANSFER_EMPTY_TRASH)) {
+ && (operation_info->kind == TRANSFER_DELETE
+ || operation_info->kind == TRANSFER_EMPTY_TRASH)) {
error_location = ERROR_LOCATION_SOURCE_PARENT;
error_kind = ERROR_NOT_ENOUGH_PERMISSIONS;
} else if ((progress_info->vfs_status == GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM
|| progress_info->vfs_status == GNOME_VFS_ERROR_READ_ONLY)
- && (transfer_info->kind == TRANSFER_MOVE
- || transfer_info->kind == TRANSFER_MOVE_TO_TRASH)
+ && (operation_info->kind == TRANSFER_MOVE
+ || operation_info->kind == TRANSFER_MOVE_TO_TRASH)
&& progress_info->phase != GNOME_VFS_XFER_CHECKING_DESTINATION) {
error_location = ERROR_LOCATION_SOURCE_PARENT;
error_kind = ERROR_READ_ONLY;
} else if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED
- && transfer_info->kind == TRANSFER_MOVE
+ && operation_info->kind == TRANSFER_MOVE
&& progress_info->phase == GNOME_VFS_XFER_PHASE_OPENTARGET) {
error_location = ERROR_LOCATION_TARGET;
error_kind = ERROR_NOT_ENOUGH_PERMISSIONS;
} else if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED
- && (transfer_info->kind == TRANSFER_MOVE
- || transfer_info->kind == TRANSFER_MOVE_TO_TRASH)
+ && (operation_info->kind == TRANSFER_MOVE
+ || operation_info->kind == TRANSFER_MOVE_TO_TRASH)
&& progress_info->phase != GNOME_VFS_XFER_CHECKING_DESTINATION) {
error_location = ERROR_LOCATION_SOURCE_OR_PARENT;
error_kind = ERROR_NOT_ENOUGH_PERMISSIONS;
} else if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED
- && (transfer_info->kind == TRANSFER_COPY
- || transfer_info->kind == TRANSFER_DUPLICATE)
+ && (operation_info->kind == TRANSFER_COPY
+ || operation_info->kind == TRANSFER_DUPLICATE)
&& (progress_info->phase == GNOME_VFS_XFER_PHASE_OPENSOURCE
|| progress_info->phase == GNOME_VFS_XFER_PHASE_COLLECTING
|| progress_info->phase == GNOME_VFS_XFER_PHASE_INITIAL)) {
@@ -996,27 +995,29 @@ handle_transfer_vfs_error (const GnomeVF
error_location = ERROR_LOCATION_TARGET;
error_kind = ERROR_NO_SPACE;
} else if (progress_info->vfs_status == GNOME_VFS_ERROR_DIRECTORY_NOT_EMPTY
- && transfer_info->kind == TRANSFER_MOVE) {
+ && operation_info->kind == TRANSFER_MOVE) {
error_location = ERROR_LOCATION_SOURCE_OR_PARENT;
error_kind = ERROR_SOURCE_IN_TARGET;
}
build_error_string (formatted_source_name, formatted_target_name,
- transfer_info->kind,
+ operation_info->kind,
error_kind, error_location,
progress_info->vfs_status,
&text, &detail);
if (error_location == ERROR_LOCATION_TARGET ||
- error_kind == ERROR_SOURCE_IN_TARGET) {
+ error_kind == ERROR_SOURCE_IN_TARGET ||
+ operation_info->kind == CREATE_FILE ||
+ operation_info->kind == CREATE_FOLDER) {
/* We can't continue, just tell the user. */
- eel_run_simple_dialog (parent_for_error_dialog (transfer_info),
+ eel_run_simple_dialog (parent_for_error_dialog (operation_info),
TRUE, GTK_MESSAGE_ERROR, text, detail, GTK_STOCK_OK, NULL);
error_dialog_result = GNOME_VFS_XFER_ERROR_ACTION_ABORT;
} else if (progress_info->files_total == 1) {
error_dialog_button_pressed = eel_run_simple_dialog
- (parent_for_error_dialog (transfer_info), TRUE,
+ (parent_for_error_dialog (operation_info), TRUE,
GTK_MESSAGE_ERROR, text,
detail, GTK_STOCK_CANCEL, _("_Retry"), NULL);
@@ -1033,7 +1034,7 @@ handle_transfer_vfs_error (const GnomeVF
}
} else {
error_dialog_button_pressed = eel_run_simple_dialog
- (parent_for_error_dialog (transfer_info), TRUE,
+ (parent_for_error_dialog (operation_info), TRUE,
GTK_MESSAGE_ERROR, text,
detail, _("_Skip"), GTK_STOCK_CANCEL, _("_Retry"), NULL);
@@ -1058,15 +1059,17 @@ handle_transfer_vfs_error (const GnomeVF
g_free (formatted_source_name);
g_free (formatted_target_name);
- nautilus_file_operations_progress_resume_timeout (transfer_info->progress_dialog);
+ if (operation_info->progress_dialog != NULL) {
+ nautilus_file_operations_progress_resume_timeout (operation_info->progress_dialog);
+ }
return error_dialog_result;
case GNOME_VFS_XFER_ERROR_MODE_ABORT:
default:
- if (transfer_info->progress_dialog != NULL) {
+ if (operation_info->progress_dialog != NULL) {
nautilus_file_operations_progress_done
- (transfer_info->progress_dialog);
+ (operation_info->progress_dialog);
}
return GNOME_VFS_XFER_ERROR_ACTION_ABORT;
}
@@ -1110,21 +1113,23 @@ is_directory (const char *uri)
static int
handle_transfer_overwrite (const GnomeVFSXferProgressInfo *progress_info,
- TransferInfo *transfer_info)
+ OperationInfo *operation_info)
{
int result;
char *text, *primary_text, *secondary_text, *formatted_name;
gboolean is_merge, target_is_dir;
- nautilus_file_operations_progress_pause_timeout (transfer_info->progress_dialog);
+ if (operation_info->progress_dialog != NULL) {
+ nautilus_file_operations_progress_pause_timeout (operation_info->progress_dialog);
+ }
/* 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
- (parent_for_error_dialog (transfer_info),
+ (parent_for_error_dialog (operation_info),
progress_info->target_name);
- if (transfer_info->kind == TRANSFER_MOVE) {
+ if (operation_info->kind == TRANSFER_MOVE) {
primary_text = g_strdup_printf (_("Could not move \"%s\" to the new location."),
formatted_name);
@@ -1140,7 +1145,7 @@ handle_transfer_overwrite (const GnomeVF
"to copy the item, rename it and try again.");
}
- eel_run_simple_dialog (parent_for_error_dialog (transfer_info),
+ eel_run_simple_dialog (parent_for_error_dialog (operation_info),
TRUE, GTK_MESSAGE_ERROR,
primary_text, secondary_text,
GTK_STOCK_OK, NULL);
@@ -1148,14 +1153,16 @@ handle_transfer_overwrite (const GnomeVF
g_free (primary_text);
g_free (formatted_name);
- nautilus_file_operations_progress_resume_timeout (transfer_info->progress_dialog);
+ if (operation_info->progress_dialog != NULL) {
+ nautilus_file_operations_progress_resume_timeout (operation_info->progress_dialog);
+ }
return GNOME_VFS_XFER_OVERWRITE_ACTION_SKIP;
}
/* transfer conflict, prompt the user to replace or skip */
formatted_name = format_and_ellipsize_uri_for_dialog (
- parent_for_error_dialog (transfer_info), progress_info->target_name);
+ parent_for_error_dialog (operation_info), progress_info->target_name);
target_is_dir = is_directory (progress_info->target_name);
if (target_is_dir) {
@@ -1180,7 +1187,7 @@ handle_transfer_overwrite (const GnomeVF
* Replace All
*/
result = eel_run_simple_dialog
- (parent_for_error_dialog (transfer_info),
+ (parent_for_error_dialog (operation_info),
TRUE,
GTK_MESSAGE_QUESTION,
text,
@@ -1188,7 +1195,9 @@ handle_transfer_overwrite (const GnomeVF
_("_Skip"), _("_Replace"), NULL);
g_free (text);
- nautilus_file_operations_progress_resume_timeout (transfer_info->progress_dialog);
+ if (operation_info->progress_dialog != NULL) {
+ nautilus_file_operations_progress_pause_timeout (operation_info->progress_dialog);
+ }
switch (result) {
case 0:
@@ -1201,12 +1210,14 @@ handle_transfer_overwrite (const GnomeVF
}
} else {
result = eel_run_simple_dialog
- (parent_for_error_dialog (transfer_info), TRUE, GTK_MESSAGE_QUESTION, text,
+ (parent_for_error_dialog (operation_info), TRUE, GTK_MESSAGE_QUESTION, text,
secondary_text,
_("S_kip All"), _("Replace _All"), _("_Skip"), _("_Replace"), NULL);
g_free (text);
- nautilus_file_operations_progress_resume_timeout (transfer_info->progress_dialog);
+ if (operation_info->progress_dialog != NULL) {
+ nautilus_file_operations_progress_resume_timeout (operation_info->progress_dialog);
+ }
switch (result) {
case 0:
@@ -1589,7 +1600,8 @@ get_duplicate_name (const char *name, in
}
static char *
-get_next_duplicate_name (char *name, int count_increment)
+get_next_duplicate_name (const char *name,
+ int count_increment)
{
char *unescaped_name;
char *unescaped_tmp_name;
@@ -1598,8 +1610,6 @@ get_next_duplicate_name (char *name, int
char *new_file;
unescaped_tmp_name = gnome_vfs_unescape_string (name, "/");
- g_free (name);
-
unescaped_name = g_filename_to_utf8 (unescaped_tmp_name, -1,
NULL, NULL, NULL);
if (!unescaped_name) {
@@ -1626,53 +1636,101 @@ get_next_duplicate_name (char *name, int
}
static int
-handle_transfer_duplicate (GnomeVFSXferProgressInfo *progress_info,
- TransferInfo *transfer_info)
+handle_operation_duplicate (GnomeVFSXferProgressInfo *progress_info,
+ OperationInfo *operation_info)
{
- switch (transfer_info->kind) {
+ char *old_name = progress_info->duplicate_name;
+ int old_count = progress_info->duplicate_count;
+
+ switch (operation_info->kind) {
case TRANSFER_LINK:
- progress_info->duplicate_name = get_link_name
- (progress_info->duplicate_name,
- progress_info->duplicate_count);
+ progress_info->duplicate_name = get_link_name (old_name, old_count);
break;
case TRANSFER_COPY:
case TRANSFER_MOVE_TO_TRASH:
- progress_info->duplicate_name = get_next_duplicate_name
- (progress_info->duplicate_name,
- progress_info->duplicate_count);
+ progress_info->duplicate_name = get_next_duplicate_name (old_name, old_count);
+ break;
+
+ case CREATE_FILE:
+ case CREATE_FOLDER:
+ if (progress_info->vfs_status == GNOME_VFS_ERROR_NAME_TOO_LONG) {
+ /* special case an 8.3 file system */
+ progress_info->duplicate_name = g_strndup (old_name, 8);
+ g_free (old_name);
+ old_name = progress_info->duplicate_name;
+
+ progress_info->duplicate_name = g_strdup_printf
+ ("%s.%d", old_name, old_count);
+ } else {
+ progress_info->duplicate_name = get_next_duplicate_name (old_name, old_count);
+ }
break;
+
default:
break;
/* For all other cases we use the name as-is. */
}
+ if (old_name != progress_info->duplicate_name) {
+ g_free (old_name);
+
+ icon_position_iterator_update_uri
+ (operation_info->iterator,
+ progress_info->target_name,
+ progress_info->duplicate_name);
+ }
+
+
return GNOME_VFS_XFER_ERROR_ACTION_SKIP;
}
static int
-update_transfer_callback (GnomeVFSAsyncHandle *handle,
- GnomeVFSXferProgressInfo *progress_info,
- gpointer data)
+async_operation_callback (GnomeVFSAsyncHandle *handle,
+ GnomeVFSXferProgressInfo *progress_info,
+ gpointer data)
{
- TransferInfo *transfer_info;
+ OperationInfo *operation_info;
+ int ret;
- transfer_info = (TransferInfo *) data;
+ operation_info = (OperationInfo *) data;
switch (progress_info->status) {
case GNOME_VFS_XFER_PROGRESS_STATUS_OK:
- return handle_transfer_ok (progress_info, transfer_info);
+ update_progress_dialog (progress_info, operation_info);
+ break;
+
case GNOME_VFS_XFER_PROGRESS_STATUS_VFSERROR:
- return handle_transfer_vfs_error (progress_info, transfer_info);
case GNOME_VFS_XFER_PROGRESS_STATUS_OVERWRITE:
- return handle_transfer_overwrite (progress_info, transfer_info);
case GNOME_VFS_XFER_PROGRESS_STATUS_DUPLICATE:
- return handle_transfer_duplicate (progress_info, transfer_info);
+ break;
+
default:
g_warning (_("Unknown GnomeVFSXferProgressStatus %d"),
progress_info->status);
return 0;
}
+
+ /* It's not entirely predictable when this is called,
+ * but when this is the case the sync call already
+ * ran before this one, so we don't want to mess up its
+ * results. Blame GnomeVFS.
+ * */
+ ret = operation_info->last_sync_response;
+
+ switch (progress_info->phase) {
+ case GNOME_VFS_XFER_PHASE_DELETESOURCE:
+ nautilus_file_changes_consume_changes (FALSE);
+ break;
+
+ case GNOME_VFS_XFER_PHASE_COMPLETED:
+ operation_info_destroy (operation_info);
+
+ default:
+ break;
+ }
+
+ return ret;
}
static void
@@ -1689,119 +1747,196 @@ apply_one_position (IconPositionIterator
}
}
-typedef struct {
- GHashTable *debuting_uris;
- IconPositionIterator *iterator;
-} SyncTransferInfo;
-
-/* Low-level callback, called for every copy engine operation.
- * Generates notifications about new, deleted and moved files.
- */
static int
-sync_transfer_callback (GnomeVFSXferProgressInfo *progress_info, gpointer data)
+handle_operation_ok (const GnomeVFSXferProgressInfo *progress_info,
+ OperationInfo *operation_info)
{
GHashTable *debuting_uris;
IconPositionIterator *position_iterator;
gboolean really_moved;
- if (data != NULL) {
- debuting_uris = ((SyncTransferInfo *) data)->debuting_uris;
- position_iterator = ((SyncTransferInfo *) data)->iterator;
- } else {
- debuting_uris = NULL;
- position_iterator = NULL;
+ if (operation_info->cancelled
+ && progress_info->phase != GNOME_VFS_XFER_PHASE_COMPLETED) {
+
+ /* If cancelled, delete any partially copied files that are laying
+ * around and return. Don't delete the source though..
+ */
+ if (progress_info->target_name != NULL
+ && progress_info->source_name != NULL
+ && strcmp (progress_info->source_name, progress_info->target_name) != 0
+ && progress_info->bytes_total != progress_info->bytes_copied) {
+ GList *delete_me;
+
+ delete_me = g_list_prepend (NULL, progress_info->target_name);
+ nautilus_file_operations_delete (delete_me, operation_info->parent_view);
+ g_list_free (delete_me);
+ }
+
+ return 0;
}
- if (progress_info->status == GNOME_VFS_XFER_PROGRESS_STATUS_OK) {
- switch (progress_info->phase) {
- case GNOME_VFS_XFER_PHASE_OPENTARGET:
- if (progress_info->top_level_item) {
- /* this is one of the selected copied or moved items -- we need
- * to make sure it's metadata gets copied over
- */
- if (progress_info->source_name == NULL) {
- /* remove any old metadata */
- nautilus_file_changes_queue_schedule_metadata_remove
- (progress_info->target_name);
- } else {
- nautilus_file_changes_queue_schedule_metadata_copy
- (progress_info->source_name, progress_info->target_name);
+ debuting_uris = operation_info->debuting_uris;
+ position_iterator = operation_info->iterator;
- }
+ switch (progress_info->phase) {
+ case GNOME_VFS_XFER_PHASE_INITIAL:
+ case GNOME_VFS_XFER_CHECKING_DESTINATION:
+ case GNOME_VFS_XFER_PHASE_COLLECTING:
+ case GNOME_VFS_XFER_PHASE_READYTOGO:
+ case GNOME_VFS_XFER_PHASE_OPENSOURCE:
+ break;
- apply_one_position (position_iterator,
- progress_info->source_name,
- progress_info->target_name);
-
- if (debuting_uris != NULL) {
- g_hash_table_replace (debuting_uris,
- g_strdup (progress_info->target_name),
- GINT_TO_POINTER (TRUE));
- }
+ case GNOME_VFS_XFER_PHASE_OPENTARGET:
+ if (progress_info->source_name == NULL) {
+ /* remove any old metadata */
+ nautilus_file_changes_queue_schedule_metadata_remove
+ (progress_info->target_name);
+ } else {
+ nautilus_file_changes_queue_schedule_metadata_copy
+ (progress_info->source_name, progress_info->target_name);
+
+ }
+
+ if (progress_info->top_level_item) {
+ apply_one_position (position_iterator,
+ progress_info->source_name,
+ progress_info->target_name);
+
+ if (debuting_uris != NULL) {
+ g_hash_table_replace (debuting_uris,
+ g_strdup (progress_info->target_name),
+ GINT_TO_POINTER (TRUE));
}
- nautilus_file_changes_queue_file_added (progress_info->target_name);
- break;
+ }
- case GNOME_VFS_XFER_PHASE_MOVING:
- g_assert (progress_info->source_name != NULL);
+ nautilus_file_changes_queue_file_added (progress_info->target_name);
+ break;
- /* If the source and target are the same, that
- * means we "moved" something in place. No
- * actual change happened, so we really don't
- * want to send out any change notification,
- * but we do want to select the files as
- * "newly moved here" so we put them into the
- * debuting_uris set.
- */
- really_moved = strcmp (progress_info->source_name,
- progress_info->target_name) != 0;
+ case GNOME_VFS_XFER_PHASE_COPYING:
+ break;
- if (progress_info->top_level_item) {
- if (really_moved) {
- nautilus_file_changes_queue_schedule_metadata_move
- (progress_info->source_name, progress_info->target_name);
- }
+ case GNOME_VFS_XFER_PHASE_MOVING:
+ g_assert (progress_info->source_name != NULL);
- apply_one_position (position_iterator,
- progress_info->source_name,
- progress_info->target_name);
-
- if (debuting_uris != NULL) {
- g_hash_table_replace (debuting_uris,
- g_strdup (progress_info->target_name),
- GINT_TO_POINTER (really_moved));
- }
+ /* If the source and target are the same, that
+ * means we "moved" something in place. No
+ * actual change happened, so we really don't
+ * want to send out any change notification,
+ * but we do want to select the files as
+ * "newly moved here" so we put them into the
+ * debuting_uris set.
+ */
+ really_moved = strcmp (progress_info->source_name,
+ progress_info->target_name) != 0;
+
+ if (really_moved) {
+ nautilus_file_changes_queue_schedule_metadata_move (progress_info->source_name,
+ progress_info->target_name);
+ }
+
+ if (progress_info->top_level_item) {
+ apply_one_position (position_iterator,
+ progress_info->source_name,
+ progress_info->target_name);
+
+ if (debuting_uris != NULL) {
+ g_hash_table_replace (debuting_uris,
+ g_strdup (progress_info->target_name),
+ GINT_TO_POINTER (really_moved));
}
+
if (really_moved) {
nautilus_file_changes_queue_file_moved (progress_info->source_name,
progress_info->target_name);
}
- break;
-
- case GNOME_VFS_XFER_PHASE_DELETESOURCE:
- g_assert (progress_info->source_name != NULL);
- if (progress_info->top_level_item) {
- nautilus_file_changes_queue_schedule_metadata_remove
- (progress_info->source_name);
- }
- nautilus_file_changes_queue_file_removed (progress_info->source_name);
- break;
-
- case GNOME_VFS_XFER_PHASE_COMPLETED:
- /* done, clean up */
- icon_position_iterator_free (position_iterator);
- /* SyncXferInfo doesn't own the debuting_uris hash table - don't free it here.
- */
- g_free (data);
- break;
+ }
- default:
- break;
+ break;
+
+ case GNOME_VFS_XFER_PHASE_READSOURCE:
+ case GNOME_VFS_XFER_PHASE_WRITETARGET:
+ case GNOME_VFS_XFER_PHASE_CLOSESOURCE:
+ case GNOME_VFS_XFER_PHASE_CLOSETARGET:
+ break;
+
+ case GNOME_VFS_XFER_PHASE_DELETESOURCE:
+ g_assert (progress_info->source_name != NULL);
+ nautilus_file_changes_queue_schedule_metadata_remove (progress_info->source_name);
+ nautilus_file_changes_queue_file_removed (progress_info->source_name);
+ break;
+
+ case GNOME_VFS_XFER_PHASE_SETATTRIBUTES:
+ case GNOME_VFS_XFER_PHASE_FILECOMPLETED:
+ case GNOME_VFS_XFER_PHASE_CLEANUP:
+ break;
+
+ case GNOME_VFS_XFER_PHASE_COMPLETED:
+ nautilus_file_changes_consume_changes (TRUE);
+
+ if (operation_info->done_callback != NULL) {
+ operation_info->done_callback (operation_info->debuting_uris,
+ operation_info->done_callback_user_data);
+ operation_info->debuting_uris = NULL;
}
+
+ /* cleanup is done in the async callback */
+ break;
+
+ default:
+ g_warning (_("Unknown GnomeVFSXferPhase %d"),
+ progress_info->phase);
+ return 0;
}
+
return 1;
}
+/* Low-level callback, called for every copy engine operation.
+ * Generates notifications about new, deleted and moved files,
+ * and handles problems.
+ */
+static int
+sync_operation_callback (GnomeVFSXferProgressInfo *progress_info,
+ gpointer data)
+{
+ OperationInfo *operation_info = (OperationInfo *) data;
+ int ret;
+
+ g_assert (operation_info != NULL);
+
+ if (progress_info->phase == GNOME_VFS_XFER_PHASE_INITIAL &&
+ operation_info->kind != CREATE_FILE &&
+ operation_info->kind != CREATE_FOLDER) {
+ create_operation_dialog (progress_info, operation_info);
+ }
+
+ switch (progress_info->status) {
+ case GNOME_VFS_XFER_PROGRESS_STATUS_OK:
+ ret = handle_operation_ok (progress_info, operation_info);
+ break;
+
+ case GNOME_VFS_XFER_PROGRESS_STATUS_VFSERROR:
+ ret = handle_operation_vfs_error (progress_info, operation_info);
+ break;
+
+ case GNOME_VFS_XFER_PROGRESS_STATUS_OVERWRITE:
+ ret = handle_transfer_overwrite (progress_info, operation_info);
+ break;
+
+ case GNOME_VFS_XFER_PROGRESS_STATUS_DUPLICATE:
+ ret = handle_operation_duplicate (progress_info, operation_info);
+ break;
+ default:
+ g_warning (_("Unknown GnomeVFSXferProgressStatus %d"),
+ progress_info->status);
+ ret = 0;
+ }
+
+ operation_info->last_sync_response = ret;
+
+ return ret;
+}
+
static gboolean
check_target_directory_is_or_in_trash (GnomeVFSURI *trash_dir_uri, GnomeVFSURI *target_dir_uri)
{
@@ -1840,8 +1975,8 @@ nautilus_file_operations_copy_move (cons
const char *target_dir,
GdkDragAction copy_action,
GtkWidget *parent_view,
- void (*done_callback) (GHashTable *debuting_uris, gpointer data),
- gpointer done_callback_data)
+ NautilusFileOperationsCallback done_callback,
+ gpointer done_callback_user_data)
{
const GList *p;
GnomeVFSXferOptions move_options;
@@ -1851,8 +1986,7 @@ nautilus_file_operations_copy_move (cons
GnomeVFSURI *trash_dir_uri;
GnomeVFSURI *uri;
- TransferInfo *transfer_info;
- SyncTransferInfo *sync_transfer_info;
+ OperationInfo *operation_info;
GnomeVFSResult result;
gboolean target_is_trash;
gboolean duplicate;
@@ -1998,7 +2132,7 @@ nautilus_file_operations_copy_move (cons
}
/* set up the copy/move parameters */
- transfer_info = transfer_info_new (parent_view);
+ operation_info = operation_info_new (parent_view);
if (relative_item_points != NULL && relative_item_points->len > 0) {
screen = gtk_widget_get_screen (GTK_WIDGET (parent_view));
screen_num = gdk_screen_get_number (screen);
@@ -2015,52 +2149,52 @@ nautilus_file_operations_copy_move (cons
/* when moving to trash, handle name conflicts automatically */
move_options |= GNOME_VFS_XFER_USE_UNIQUE_NAMES;
/* localizers: progress dialog title */
- transfer_info->operation_title = _("Moving files to the Trash");
+ operation_info->operation_title = _("Moving files to the Trash");
/* localizers: label prepended to the progress count */
- transfer_info->action_label =_("Throwing out file:");
+ operation_info->action_label =_("Throwing out file:");
/* localizers: label prepended to the name of the current file moved */
- transfer_info->progress_verb =_("Moving");
- transfer_info->preparation_name =_("Preparing to Move to Trash...");
+ operation_info->progress_verb =_("Moving");
+ operation_info->preparation_name =_("Preparing to Move to Trash...");
- transfer_info->kind = TRANSFER_MOVE_TO_TRASH;
+ operation_info->kind = TRANSFER_MOVE_TO_TRASH;
} else if ((move_options & GNOME_VFS_XFER_REMOVESOURCE) != 0) {
/* localizers: progress dialog title */
- transfer_info->operation_title = _("Moving files");
+ operation_info->operation_title = _("Moving files");
/* localizers: label prepended to the progress count */
- transfer_info->action_label =_("Moving file:");
+ operation_info->action_label =_("Moving file:");
/* localizers: label prepended to the name of the current file moved */
- transfer_info->progress_verb =_("Moving");
- transfer_info->preparation_name =_("Preparing To Move...");
- transfer_info->cleanup_name = _("Finishing Move...");
+ operation_info->progress_verb =_("Moving");
+ operation_info->preparation_name =_("Preparing To Move...");
+ operation_info->cleanup_name = _("Finishing Move...");
- transfer_info->kind = TRANSFER_MOVE;
+ operation_info->kind = TRANSFER_MOVE;
} else if ((move_options & GNOME_VFS_XFER_LINK_ITEMS) != 0) {
/* when creating links, handle name conflicts automatically */
move_options |= GNOME_VFS_XFER_USE_UNIQUE_NAMES;
/* localizers: progress dialog title */
- transfer_info->operation_title = _("Creating links to files");
+ operation_info->operation_title = _("Creating links to files");
/* localizers: label prepended to the progress count */
- transfer_info->action_label =_("Linking file:");
+ operation_info->action_label =_("Linking file:");
/* localizers: label prepended to the name of the current file linked */
- transfer_info->progress_verb =_("Linking");
- transfer_info->preparation_name = _("Preparing to Create Links...");
- transfer_info->cleanup_name = _("Finishing Creating Links...");
+ operation_info->progress_verb =_("Linking");
+ operation_info->preparation_name = _("Preparing to Create Links...");
+ operation_info->cleanup_name = _("Finishing Creating Links...");
- transfer_info->kind = TRANSFER_LINK;
+ operation_info->kind = TRANSFER_LINK;
} else {
/* localizers: progress dialog title */
- transfer_info->operation_title = _("Copying files");
+ operation_info->operation_title = _("Copying files");
/* localizers: label prepended to the progress count */
- transfer_info->action_label =_("Copying file:");
+ operation_info->action_label =_("Copying file:");
/* localizers: label prepended to the name of the current file copied */
- transfer_info->progress_verb =_("Copying");
- transfer_info->preparation_name =_("Preparing To Copy...");
- transfer_info->cleanup_name = "";
+ operation_info->progress_verb =_("Copying");
+ operation_info->preparation_name =_("Preparing To Copy...");
+ operation_info->cleanup_name = "";
- transfer_info->kind = TRANSFER_COPY;
+ operation_info->kind = TRANSFER_COPY;
}
/* we'll need to check for copy into Trash and for moving/copying the Trash itself */
@@ -2151,25 +2285,20 @@ nautilus_file_operations_copy_move (cons
}
}
- transfer_info->error_mode = GNOME_VFS_XFER_ERROR_MODE_QUERY;
- transfer_info->overwrite_mode = GNOME_VFS_XFER_OVERWRITE_MODE_QUERY;
- transfer_info->done_callback = done_callback;
- transfer_info->done_callback_data = done_callback_data;
- transfer_info->debuting_uris = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-
- sync_transfer_info = g_new (SyncTransferInfo, 1);
- sync_transfer_info->iterator = icon_position_iterator;
- sync_transfer_info->debuting_uris = transfer_info->debuting_uris;
+ operation_info->error_mode = GNOME_VFS_XFER_ERROR_MODE_QUERY;
+ operation_info->overwrite_mode = GNOME_VFS_XFER_OVERWRITE_MODE_QUERY;
+ operation_info->done_callback = done_callback;
+ operation_info->done_callback_user_data = done_callback_user_data;
- transfer_info->iterator = sync_transfer_info->iterator;
+ operation_info->iterator = icon_position_iterator;
if (result == GNOME_VFS_OK) {
- gnome_vfs_async_xfer (&transfer_info->handle, source_uri_list, target_uri_list,
+ gnome_vfs_async_xfer (&operation_info->handle, source_uri_list, target_uri_list,
move_options, GNOME_VFS_XFER_ERROR_MODE_QUERY,
GNOME_VFS_XFER_OVERWRITE_MODE_QUERY,
GNOME_VFS_PRIORITY_DEFAULT,
- update_transfer_callback, transfer_info,
- sync_transfer_callback, sync_transfer_info);
+ async_operation_callback, operation_info,
+ sync_operation_callback, operation_info);
}
gnome_vfs_uri_list_free (source_uri_list);
@@ -2181,123 +2310,62 @@ nautilus_file_operations_copy_move (cons
}
typedef struct {
- GnomeVFSAsyncHandle *handle;
- NautilusNewFolderCallback done_callback;
- gpointer data;
- GtkWidget *parent_view;
- IconPositionIterator *iterator;
-} NewFolderTransferState;
+ NautilusNewFileCallback callback;
+ gpointer callback_user_data;
+} NewFileInfo;
-static int
-handle_new_folder_vfs_error (const GnomeVFSXferProgressInfo *progress_info, NewFolderTransferState *state)
+static void
+get_new_file_uri (gpointer key,
+ gpointer value,
+ gpointer user_data)
{
- const char *error_string;
- char *error_string_to_free;
+ char *uri;
+ char **uri_out;
- error_string_to_free = NULL;
+ uri = key;
+ uri_out = user_data;
- if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED) {
- error_string = _("You do not have permissions to write to the destination.");
- } else if (progress_info->vfs_status == GNOME_VFS_ERROR_NO_SPACE) {
- error_string = _("There is no space on the destination.");
- } else {
- error_string = g_strdup_printf (_("Error \"%s\" creating new folder."),
- gnome_vfs_result_to_string (progress_info->vfs_status));
- error_string_to_free = (char *)error_string;
- }
-
- eel_show_error_dialog (_("Error creating new folder."), error_string,
- GTK_WINDOW (gtk_widget_get_toplevel (state->parent_view)));
-
- g_free (error_string_to_free);
-
- return GNOME_VFS_XFER_ERROR_ACTION_ABORT;
+ *uri_out = uri;
}
-static int
-new_folder_transfer_callback (GnomeVFSAsyncHandle *handle,
- GnomeVFSXferProgressInfo *progress_info,
- gpointer data)
-{
- NewFolderTransferState *state;
- char *temp_string;
- char *new_uri;
-
- state = (NewFolderTransferState *) data;
+static void
+new_file_done_callback (GHashTable *debuting_uris,
+ gpointer user_data)
+{
+ NewFileInfo *new_file_info = (NewFileInfo *) user_data;
+ char *uri;
- switch (progress_info->phase) {
+ g_assert (new_file_info != NULL);
- case GNOME_VFS_XFER_PHASE_COMPLETED:
- eel_remove_weak_pointer (&state->parent_view);
- g_free (state);
- return 0;
+ uri = NULL;
- default:
- switch (progress_info->status) {
- case GNOME_VFS_XFER_PROGRESS_STATUS_OK:
- nautilus_file_changes_consume_changes (TRUE);
- new_uri = NULL;
- if (progress_info->vfs_status == GNOME_VFS_OK) {
- new_uri = progress_info->target_name;
- }
- (* state->done_callback) (new_uri,
- state->data);
- return 1;
-
- case GNOME_VFS_XFER_PROGRESS_STATUS_DUPLICATE:
-
- temp_string = progress_info->duplicate_name;
-
- if (progress_info->vfs_status == GNOME_VFS_ERROR_NAME_TOO_LONG) {
- /* special case an 8.3 file system */
- progress_info->duplicate_name = g_strndup (temp_string, 8);
- progress_info->duplicate_name[8] = '\0';
- g_free (temp_string);
- temp_string = progress_info->duplicate_name;
- progress_info->duplicate_name = g_strdup_printf
- ("%s.%d",
- progress_info->duplicate_name,
- progress_info->duplicate_count);
- } else {
- progress_info->duplicate_name = g_strdup_printf
- ("%s%%20%d",
- progress_info->duplicate_name,
- progress_info->duplicate_count);
- }
- g_free (temp_string);
-
- icon_position_iterator_update_uri
- (state->iterator,
- progress_info->target_name,
- progress_info->duplicate_name);
+ if (debuting_uris != NULL) {
+ g_hash_table_foreach (debuting_uris, get_new_file_uri, &uri);
+ }
- return GNOME_VFS_XFER_ERROR_ACTION_SKIP;
-
- case GNOME_VFS_XFER_PROGRESS_STATUS_VFSERROR:
- return handle_new_folder_vfs_error (progress_info, state);
-
-
+ if (new_file_info->callback != NULL) {
+ (* new_file_info->callback) (uri, new_file_info->callback_user_data);
+ }
- default:
- g_warning (_("Unknown GnomeVFSXferProgressStatus %d"),
- progress_info->status);
- return 0;
- }
+ if (debuting_uris != NULL) {
+ g_hash_table_destroy (debuting_uris);
}
+
+ g_free (new_file_info);
}
void
nautilus_file_operations_new_folder (GtkWidget *parent_view,
GdkPoint *target_point,
const char *parent_dir,
- NautilusNewFolderCallback done_callback,
- gpointer data)
+ NautilusNewFileCallback done_callback,
+ gpointer done_callback_user_data)
{
GList *target_uri_list;
GnomeVFSURI *uri, *parent_uri;
char *text_uri, *dirname;
- NewFolderTransferState *state;
- SyncTransferInfo *sync_transfer_info;
+ OperationInfo *operation_info;
+ NewFileInfo *new_file_info;
/* pass in the target directory and the new folder name as a destination URI */
parent_uri = gnome_vfs_uri_new (parent_dir);
@@ -2310,165 +2378,34 @@ nautilus_file_operations_new_folder (Gtk
text_uri = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
- sync_transfer_info = g_new (SyncTransferInfo, 1);
- sync_transfer_info->iterator = icon_position_iterator_new_single
+ operation_info = operation_info_new (parent_view);
+ operation_info->iterator = icon_position_iterator_new_single
(target_point, text_uri,
gdk_screen_get_number (gtk_widget_get_screen (parent_view)),
FALSE);
- sync_transfer_info->debuting_uris = NULL;
+ operation_info->kind = CREATE_FOLDER;
- g_free (text_uri);
+ new_file_info = g_new (NewFileInfo, 1);
+ new_file_info->callback = done_callback;
+ new_file_info->callback_user_data = done_callback_user_data;
- state = g_new (NewFolderTransferState, 1);
- state->done_callback = done_callback;
- state->data = data;
- state->parent_view = parent_view;
- state->iterator = sync_transfer_info->iterator;
- eel_add_weak_pointer (&state->parent_view);
+ operation_info->done_callback = new_file_done_callback;
+ operation_info->done_callback_user_data = new_file_info;
- gnome_vfs_async_xfer (&state->handle, NULL, target_uri_list,
+ g_free (text_uri);
+
+ gnome_vfs_async_xfer (&operation_info->handle, NULL, target_uri_list,
GNOME_VFS_XFER_NEW_UNIQUE_DIRECTORY,
GNOME_VFS_XFER_ERROR_MODE_QUERY,
GNOME_VFS_XFER_OVERWRITE_MODE_QUERY,
GNOME_VFS_PRIORITY_DEFAULT,
- new_folder_transfer_callback, state,
- sync_transfer_callback, sync_transfer_info);
+ async_operation_callback, operation_info,
+ sync_operation_callback, operation_info);
gnome_vfs_uri_list_free (target_uri_list);
gnome_vfs_uri_unref (parent_uri);
}
-typedef struct {
- GnomeVFSAsyncHandle *handle;
- NautilusNewFileCallback done_callback;
- gpointer data;
- GtkWidget *parent_view;
- GHashTable *debuting_uris;
- IconPositionIterator *iterator;
-} NewFileTransferState;
-
-
-static int
-handle_new_file_vfs_error (const GnomeVFSXferProgressInfo *progress_info, NewFileTransferState *state)
-{
- const char *error_string;
- char *error_string_to_free;
-
- error_string_to_free = NULL;
-
- if (progress_info->vfs_status == GNOME_VFS_ERROR_ACCESS_DENIED) {
- error_string = _("You do not have permissions to write to the destination.");
- } else if (progress_info->vfs_status == GNOME_VFS_ERROR_NO_SPACE) {
- error_string = _("There is no space on the destination.");
- } else {
- error_string = g_strdup_printf (_("Error \"%s\" creating new document."),
- gnome_vfs_result_to_string (progress_info->vfs_status));
- error_string_to_free = (char *)error_string;
- }
-
- eel_show_error_dialog (_("Error creating new document."), error_string,
- GTK_WINDOW (gtk_widget_get_toplevel (state->parent_view)));
-
- g_free (error_string_to_free);
-
- return GNOME_VFS_XFER_ERROR_ACTION_ABORT;
-}
-
-static void
-get_new_file_uri (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- char *uri;
- char **uri_out;
-
- uri = key;
- uri_out = user_data;
-
- *uri_out = uri;
-}
-
-
-static int
-new_file_transfer_callback (GnomeVFSAsyncHandle *handle,
- GnomeVFSXferProgressInfo *progress_info,
- gpointer data)
-{
- NewFileTransferState *state;
- char *temp_string;
- char **temp_strings;
- char *uri;
-
- state = (NewFileTransferState *) data;
-
- switch (progress_info->phase) {
-
- case GNOME_VFS_XFER_PHASE_COMPLETED:
- uri = NULL;
-
- g_hash_table_foreach (state->debuting_uris,
- get_new_file_uri, &uri);
-
- (* state->done_callback) (uri, state->data);
- /* uri is owned by hashtable, don't free */
- eel_remove_weak_pointer (&state->parent_view);
- g_hash_table_destroy (state->debuting_uris);
- g_free (state);
- return 0;
-
- default:
- switch (progress_info->status) {
- case GNOME_VFS_XFER_PROGRESS_STATUS_OK:
- nautilus_file_changes_consume_changes (TRUE);
- return 1;
-
- case GNOME_VFS_XFER_PROGRESS_STATUS_DUPLICATE:
-
- temp_string = progress_info->duplicate_name;
-
- if (progress_info->vfs_status == GNOME_VFS_ERROR_NAME_TOO_LONG) {
- /* special case an 8.3 file system */
- progress_info->duplicate_name = g_strndup (temp_string, 8);
- progress_info->duplicate_name[8] = '\0';
- g_free (temp_string);
- temp_string = progress_info->duplicate_name;
- progress_info->duplicate_name = g_strdup_printf
- ("%s.%d",
- progress_info->duplicate_name,
- progress_info->duplicate_count);
- } else {
- temp_strings = g_strsplit (temp_string, ".", 2);
- if (temp_strings[1] != NULL) {
- progress_info->duplicate_name = g_strdup_printf
- ("%s%%20%d.%s",
- temp_strings[0],
- progress_info->duplicate_count,
- temp_strings[1]);
- } else {
- progress_info->duplicate_name = g_strdup_printf
- ("%s%%20%d",
- progress_info->duplicate_name,
- progress_info->duplicate_count);
- }
- g_strfreev (temp_strings);
- }
- g_free (temp_string);
-
- return GNOME_VFS_XFER_ERROR_ACTION_SKIP;
-
- case GNOME_VFS_XFER_PROGRESS_STATUS_VFSERROR:
- return handle_new_file_vfs_error (progress_info, state);
-
-
-
- default:
- g_warning (_("Unknown GnomeVFSXferProgressStatus %d"),
- progress_info->status);
- return 0;
- }
- }
-}
-
void
nautilus_file_operations_new_file_from_template (GtkWidget *parent_view,
GdkPoint *target_point,
@@ -2476,14 +2413,14 @@ nautilus_file_operations_new_file_from_t
const char *target_filename,
const char *template_uri,
NautilusNewFileCallback done_callback,
- gpointer data)
+ gpointer done_callback_user_data)
{
GList *target_uri_list;
GList *source_uri_list;
GnomeVFSURI *target_uri, *parent_uri, *source_uri;
GnomeVFSXferOptions options;
- NewFileTransferState *state;
- SyncTransferInfo *sync_transfer_info;
+ OperationInfo *operation_info;
+ NewFileInfo *new_file_info;
char *tmp;
g_assert (parent_dir != NULL);
@@ -2494,7 +2431,7 @@ nautilus_file_operations_new_file_from_t
source_uri = gnome_vfs_uri_new (template_uri);
if (source_uri == NULL) {
- (*done_callback) (NULL, data);
+ (*done_callback) (NULL, done_callback_user_data);
return;
}
@@ -2506,33 +2443,33 @@ nautilus_file_operations_new_file_from_t
g_free (tmp);
}
- sync_transfer_info = g_new (SyncTransferInfo, 1);
- sync_transfer_info->iterator = icon_position_iterator_new_single
+ operation_info = operation_info_new (parent_view);
+ operation_info->iterator = icon_position_iterator_new_single
(target_point, template_uri,
gdk_screen_get_number (gtk_widget_get_screen (parent_view)),
TRUE);
- sync_transfer_info->debuting_uris = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ operation_info->kind = CREATE_FILE;
+
+ new_file_info = g_new (NewFileInfo, 1);
+ new_file_info->callback = done_callback;
+ new_file_info->callback_user_data = done_callback_user_data;
- state = g_new (NewFileTransferState, 1);
- state->done_callback = done_callback;
- state->data = data;
- state->parent_view = parent_view;
- state->iterator = sync_transfer_info->iterator;
- state->debuting_uris = sync_transfer_info->debuting_uris;
- eel_add_weak_pointer (&state->parent_view);
+ operation_info->done_callback = new_file_done_callback;
+ operation_info->done_callback_user_data = new_file_info;
target_uri_list = g_list_prepend (NULL, target_uri);
source_uri_list = g_list_prepend (NULL, source_uri);
options = GNOME_VFS_XFER_USE_UNIQUE_NAMES;
- gnome_vfs_async_xfer (&state->handle, source_uri_list, target_uri_list,
+ gnome_vfs_async_xfer (&operation_info->handle,
+ source_uri_list, target_uri_list,
options,
GNOME_VFS_XFER_ERROR_MODE_QUERY,
GNOME_VFS_XFER_OVERWRITE_MODE_QUERY,
GNOME_VFS_PRIORITY_DEFAULT,
- new_file_transfer_callback, state,
- sync_transfer_callback, sync_transfer_info);
+ async_operation_callback, operation_info,
+ sync_operation_callback, operation_info);
gnome_vfs_uri_list_free (target_uri_list);
gnome_vfs_uri_list_free (source_uri_list);
@@ -2622,7 +2559,7 @@ nautilus_file_operations_delete (const G
const GList *p;
const char *item_uri;
NautilusFile *file;
- TransferInfo *transfer_info;
+ OperationInfo *operation_info;
uri_list = NULL;
for (p = item_uris; p != NULL; p = p->next) {
@@ -2656,28 +2593,28 @@ nautilus_file_operations_delete (const G
return;
}
- transfer_info = transfer_info_new (parent_view);
+ operation_info = operation_info_new (parent_view);
/* localizers: progress dialog title */
- transfer_info->operation_title = _("Deleting files");
+ operation_info->operation_title = _("Deleting files");
/* localizers: label prepended to the progress count */
- transfer_info->action_label =_("Files deleted:");
+ operation_info->action_label =_("Files deleted:");
/* localizers: label prepended to the name of the current file deleted */
- transfer_info->progress_verb =_("Deleting");
- transfer_info->preparation_name =_("Preparing to Delete files...");
- transfer_info->cleanup_name ="";
-
- transfer_info->error_mode = GNOME_VFS_XFER_ERROR_MODE_QUERY;
- transfer_info->overwrite_mode = GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE;
- transfer_info->kind = TRANSFER_DELETE;
+ operation_info->progress_verb =_("Deleting");
+ operation_info->preparation_name =_("Preparing to Delete files...");
+ operation_info->cleanup_name ="";
+
+ operation_info->error_mode = GNOME_VFS_XFER_ERROR_MODE_QUERY;
+ operation_info->overwrite_mode = GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE;
+ operation_info->kind = TRANSFER_DELETE;
- gnome_vfs_async_xfer (&transfer_info->handle, uri_list, NULL,
+ gnome_vfs_async_xfer (&operation_info->handle, uri_list, NULL,
GNOME_VFS_XFER_DELETE_ITEMS | GNOME_VFS_XFER_RECURSIVE,
GNOME_VFS_XFER_ERROR_MODE_QUERY,
GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE,
GNOME_VFS_PRIORITY_DEFAULT,
- update_transfer_callback, transfer_info,
- sync_transfer_callback, NULL);
+ async_operation_callback, operation_info,
+ sync_operation_callback, operation_info);
gnome_vfs_uri_list_free (uri_list);
}
@@ -2685,33 +2622,33 @@ nautilus_file_operations_delete (const G
static void
do_empty_trash (GtkWidget *parent_view)
{
- TransferInfo *transfer_info;
+ OperationInfo *operation_info;
GList *trash_dir_list;
trash_dir_list = nautilus_trash_monitor_get_trash_directories ();
if (trash_dir_list != NULL) {
/* set up the move parameters */
- transfer_info = transfer_info_new (parent_view);
+ operation_info = operation_info_new (parent_view);
/* localizers: progress dialog title */
- transfer_info->operation_title = _("Emptying the Trash");
+ operation_info->operation_title = _("Emptying the Trash");
/* localizers: label prepended to the progress count */
- transfer_info->action_label =_("Files deleted:");
+ operation_info->action_label =_("Files deleted:");
/* localizers: label prepended to the name of the current file deleted */
- transfer_info->progress_verb =_("Deleting");
- transfer_info->preparation_name =_("Preparing to Empty the Trash...");
- transfer_info->cleanup_name ="";
- transfer_info->error_mode = GNOME_VFS_XFER_ERROR_MODE_QUERY;
- transfer_info->overwrite_mode = GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE;
- transfer_info->kind = TRANSFER_EMPTY_TRASH;
+ operation_info->progress_verb =_("Deleting");
+ operation_info->preparation_name =_("Preparing to Empty the Trash...");
+ operation_info->cleanup_name ="";
+ operation_info->error_mode = GNOME_VFS_XFER_ERROR_MODE_QUERY;
+ operation_info->overwrite_mode = GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE;
+ operation_info->kind = TRANSFER_EMPTY_TRASH;
- gnome_vfs_async_xfer (&transfer_info->handle, trash_dir_list, NULL,
+ gnome_vfs_async_xfer (&operation_info->handle, trash_dir_list, NULL,
GNOME_VFS_XFER_EMPTY_DIRECTORIES,
GNOME_VFS_XFER_ERROR_MODE_QUERY,
GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE,
GNOME_VFS_PRIORITY_DEFAULT,
- update_transfer_callback, transfer_info,
- sync_transfer_callback, NULL);
+ async_operation_callback, operation_info,
+ sync_operation_callback, operation_info);
}
gnome_vfs_uri_list_free (trash_dir_list);
Attachment:
signature.asc
Description: Dies ist ein digital signierter Nachrichtenteil