diff options
22 files changed, 667 insertions, 177 deletions
@@ -1,3 +1,47 @@ +2000-07-04 Pavel Cisler <pavel@eazel.com> + + * src/file-manager/dfos-xfer-progress-dialog.c: + * src/file-manager/dfos-xfer-progress-dialog.h: + (handle_xfer_ok), + (fs_xfer), (fs_move_to_trash), (fs_delete), (fs_empty_trash): + * src/file-manager/dfos-xfer-progress-dialog.c: + (dfos_xfer_progress_dialog_clear): + Fixed 1215 - inter-volume move now removes the source files. + Made it so that when an inter-volume copy has ended and source files + are removed, the progress dialog updates. Added a new cleanup phase + string. + + * src/file-manager/dfos-xfer-progress-dialog.c: + (dfos_xfer_progress_dialog_new_file), + (set_text_unescaped_trimmed): + Added code to unescape paths in progress dialogs. + + * src/file-manager/dfos-xfer.c: + * src/file-manager/dfos-xfer.h: + (nautilus_convert_to_unescaped_string_for_display), + (handle_xfer_vfs_error), (handle_xfer_overwrite): + Added code to unescape paths in error dialogs. + + * libnautilus-extensions/nautilus-drag.c: + (nautilus_drag_default_drop_action), + (nautilus_drag_modifier_based_action): + * libnautilus-extensions/nautilus-drag.h: + * libnautilus-extensions/nautilus-icon-dnd.c: + (handle_nonlocal_move), (nautilus_icon_container_find_drop_target), + (nautilus_icon_container_receive_dropped_icons), + (nautilus_icon_container_get_drop_action), (drag_motion_callback): + * libnautilus-extensions/nautilus-list.c: + (nautilus_list_drag_motion): + Reworked a whole lot to allow me to update the default copy action + based on the drag&drop context - an inter-volume drag&drop will now + suggest a copy as a default. + Moved out more sharable code into nautilus-drag.c. + Added a common routine for figuring out the drop target. + + * src/file-manager/fm-directory-view.c: (fm_directory_is_trash), + (fm_directory_can_move_to_trash): + Fixed a bunch of asserts caused by unreffing NULL uris. + 2000-07-04 Michael Meeks <michael@helixcode.com> * libnautilus-extensions/bonobo-stream-vfs.c (vfs_read): update diff --git a/libnautilus-extensions/nautilus-drag.c b/libnautilus-extensions/nautilus-drag.c index 6b16298cf..b05d55074 100644 --- a/libnautilus-extensions/nautilus-drag.c +++ b/libnautilus-extensions/nautilus-drag.c @@ -27,6 +27,7 @@ #include <libgnomevfs/gnome-vfs-types.h> #include <libgnomevfs/gnome-vfs-uri.h> +#include <libgnomevfs/gnome-vfs-ops.h> #include <string.h> #include <stdio.h> @@ -242,6 +243,37 @@ nautilus_drag_can_accept_items (NautilusFile *drop_target_item, return TRUE; } +void +nautilus_drag_default_drop_action (const char *target_uri_string, const GList *items, + int *default_action, int *non_default_action) +{ + gboolean same_fs; + GnomeVFSURI *target_uri; + GnomeVFSURI *dropped_uri; + + if (target_uri_string == NULL) { + *default_action = 0; + *non_default_action = 0; + return; + } + + target_uri = gnome_vfs_uri_new (target_uri_string); + + /* Compare the first dropped uri with the target uri for same fs match. */ + dropped_uri = gnome_vfs_uri_new (((DragSelectionItem *)items->data)->uri); + same_fs = TRUE; + gnome_vfs_check_same_fs_uris (target_uri, dropped_uri, &same_fs); + gnome_vfs_uri_unref (dropped_uri); + gnome_vfs_uri_unref (target_uri); + + if (same_fs) { + *default_action = GDK_ACTION_MOVE; + *non_default_action = GDK_ACTION_COPY; + } else { + *default_action = GDK_ACTION_COPY; + *non_default_action = GDK_ACTION_MOVE; + } +} /* Encode a "x-special/gnome-icon-list" selection. Along with the URIs of the dragged files, this encodes @@ -311,17 +343,17 @@ nautilus_drag_drag_data_get (GtkWidget *widget, } int -nautilus_drag_modifier_based_action () +nautilus_drag_modifier_based_action (int default_action, int non_default_action) { GdkModifierType modifiers; gdk_window_get_pointer (NULL, NULL, NULL, &modifiers); if ((modifiers & GDK_CONTROL_MASK) != 0) { - return GDK_ACTION_COPY; + return non_default_action; } else if ((modifiers & GDK_MOD1_MASK) != 0) { return GDK_ACTION_LINK; } - return GDK_ACTION_MOVE; + return default_action; } diff --git a/libnautilus-extensions/nautilus-drag.h b/libnautilus-extensions/nautilus-drag.h index 702743fba..c6452155a 100644 --- a/libnautilus-extensions/nautilus-drag.h +++ b/libnautilus-extensions/nautilus-drag.h @@ -102,6 +102,10 @@ gboolean nautilus_drag_can_accept_item (NautilusFile *drop_target_item, const char *item_uri); gboolean nautilus_drag_can_accept_items (NautilusFile *drop_target_item, const GList *items); +void nautilus_drag_default_drop_action (const char *target_uri, + const GList *items, + int *default_action, + int *non_default_action); gboolean nautilus_drag_drag_data_get (GtkWidget *widget, GdkDragContext *context, @@ -110,6 +114,7 @@ gboolean nautilus_drag_drag_data_get (GtkWidget *widget, guint32 time, gpointer container_context, NautilusDragEachSelectedItemIterator each_selected_item_iterator); -int nautilus_drag_modifier_based_action (void); +int nautilus_drag_modifier_based_action (int default_action, + int non_default_action); #endif diff --git a/libnautilus-extensions/nautilus-file-operations-progress.c b/libnautilus-extensions/nautilus-file-operations-progress.c index 093eab029..1ccd468e6 100644 --- a/libnautilus-extensions/nautilus-file-operations-progress.c +++ b/libnautilus-extensions/nautilus-file-operations-progress.c @@ -19,9 +19,13 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - Author: Ettore Perazzoli <ettore@gnu.org> */ + Authors: + Ettore Perazzoli <ettore@gnu.org> + Pavel Cisler <pavel@eazel.com> + */ #include <config.h> +#include <libgnomevfs/gnome-vfs-utils.h> #include "dfos-xfer-progress-dialog.h" #include <gnome.h> @@ -79,49 +83,61 @@ trim_string (const char *string, } static void -set_text_trimmed (GtkLabel *label, - const char *text, - const char *trimmable_text, - guint max_width) +set_text_unescaped_trimmed (GtkLabel *label, + const char *text, + const char *trimmable_text, + guint max_width) { GdkFont *font; + char *unescaped_text; char *trimmed_text; + char *unescaped_trimmable_text; char *s; guint text_width; guint trimmable_text_width; font = GTK_WIDGET (label)->style->font; - if (text != NULL) - text_width = gdk_string_width (font, text); - else + trimmed_text = NULL; + unescaped_text = NULL; + unescaped_trimmable_text = NULL; + + if (text) { + unescaped_text = gnome_vfs_unescape_string_for_display (text); + } + if (trimmable_text) { + unescaped_trimmable_text = gnome_vfs_unescape_string_for_display (trimmable_text); + } + + if (unescaped_text != NULL) { + text_width = gdk_string_width (font, unescaped_text); + } else { text_width = 0; + } - if (trimmable_text != NULL) - trimmable_text_width = gdk_string_width (font, trimmable_text); + if (unescaped_trimmable_text != NULL) + trimmable_text_width = gdk_string_width (font, unescaped_trimmable_text); else trimmable_text_width = 0; if (text_width + trimmable_text_width <= max_width) { - s = g_strconcat (text, trimmable_text, NULL); - gtk_label_set_text (GTK_LABEL (label), s); - g_free (s); - return; + s = g_strconcat (unescaped_text, unescaped_trimmable_text, NULL); + } else { + + trimmed_text = trim_string (unescaped_trimmable_text, + font, + max_width - text_width, + trimmable_text_width); + s = g_strconcat (unescaped_text, trimmed_text, NULL); } - trimmed_text = trim_string (trimmable_text, - font, - max_width - text_width, - trimmable_text_width); - s = g_strconcat (text, trimmed_text, NULL); - gtk_label_set_text (GTK_LABEL (label), s); - g_free (s); g_free (trimmed_text); + g_free (unescaped_text); + g_free (unescaped_trimmable_text); } - /* GnomeDialog signals. */ /* This is just to make sure the dialog is not closed without explicit @@ -135,7 +151,6 @@ do_close (GnomeDialog *dialog) return FALSE; } - /* GtkObject methods. */ static void @@ -148,7 +163,6 @@ destroy (GtkObject *object) g_free (dialog->operation_string); } - /* Initialization. */ static GtkWidget * @@ -215,7 +229,6 @@ class_init (DFOSXferProgressDialogClass *class) dialog_class->close = do_close; } - /* Public functions. */ guint @@ -320,20 +333,30 @@ dfos_xfer_progress_dialog_new_file (DFOSXferProgressDialog *dialog, gtk_label_set_text (GTK_LABEL (dialog->operation_label), s); g_free (s); - set_text_trimmed (GTK_LABEL (dialog->source_label), - dialog->from_prefix, source_uri, - DIALOG_WIDTH); + set_text_unescaped_trimmed (GTK_LABEL (dialog->source_label), + dialog->from_prefix, source_uri, DIALOG_WIDTH); if (dialog->to_prefix != NULL && dialog->target_label != NULL) - set_text_trimmed (GTK_LABEL (dialog->target_label), - dialog->to_prefix, target_uri, - DIALOG_WIDTH); + set_text_unescaped_trimmed (GTK_LABEL (dialog->target_label), + dialog->to_prefix, target_uri, DIALOG_WIDTH); update (dialog); } void +dfos_xfer_progress_dialog_clear (DFOSXferProgressDialog *dialog) +{ + gtk_label_set_text (GTK_LABEL (dialog->source_label), ""); + gtk_label_set_text (GTK_LABEL (dialog->target_label), ""); + + dialog->files_total = 0; + dialog->bytes_total = 0; + + update (dialog); +} + +void dfos_xfer_progress_dialog_update (DFOSXferProgressDialog *dialog, gulong bytes_done_in_file, gulong bytes_done) @@ -346,7 +369,6 @@ dfos_xfer_progress_dialog_update (DFOSXferProgressDialog *dialog, update (dialog); } - void dfos_xfer_progress_dialog_freeze (DFOSXferProgressDialog *dialog) { diff --git a/libnautilus-extensions/nautilus-file-operations-progress.h b/libnautilus-extensions/nautilus-file-operations-progress.h index e96e719ca..6ff75cb16 100644 --- a/libnautilus-extensions/nautilus-file-operations-progress.h +++ b/libnautilus-extensions/nautilus-file-operations-progress.h @@ -86,6 +86,9 @@ void dfos_xfer_progress_dialog_set_operation_string (DFOSXferProgressDialog *dialog, const char *operation_string); +void dfos_xfer_progress_dialog_clear + (DFOSXferProgressDialog *dialog); + void dfos_xfer_progress_dialog_new_file (DFOSXferProgressDialog *dialog, const char *source_uri, diff --git a/libnautilus-extensions/nautilus-file-operations.c b/libnautilus-extensions/nautilus-file-operations.c index 38361d331..5c1ea82be 100644 --- a/libnautilus-extensions/nautilus-file-operations.c +++ b/libnautilus-extensions/nautilus-file-operations.c @@ -42,12 +42,12 @@ typedef enum { XFER_DELETE } XferKind; - typedef struct XferInfo { GnomeVFSAsyncHandle *handle; GtkWidget *progress_dialog; const char *operation_name; const char *preparation_name; + const char *cleanup_name; GnomeVFSXferErrorMode error_mode; GnomeVFSXferOverwriteMode overwrite_mode; GtkWidget *parent_view; @@ -75,6 +75,19 @@ xfer_info_new (GnomeVFSAsyncHandle *handle, return info; } +char * +nautilus_convert_to_unescaped_string_for_display (char *escaped) +{ + char *result; + if (!escaped) { + return NULL; + } + result = gnome_vfs_unescape_string_for_display (escaped); + g_free (escaped); + return result; +} + + static void xfer_dialog_clicked_callback (DFOSXferProgressDialog *dialog, int button_number, @@ -153,6 +166,7 @@ handle_xfer_ok (const GnomeVFSXferProgressInfo *progress_info, case GNOME_VFS_XFER_PHASE_COPYING: if (xfer_info->progress_dialog != NULL) { + if (progress_info->bytes_copied == 0) { dfos_xfer_progress_dialog_new_file (DFOS_XFER_PROGRESS_DIALOG @@ -181,6 +195,18 @@ handle_xfer_ok (const GnomeVFSXferProgressInfo *progress_info, } return TRUE; + case GNOME_VFS_XFER_PHASE_CLEANUP: + if (xfer_info->progress_dialog != NULL) { + dfos_xfer_progress_dialog_clear( + DFOS_XFER_PROGRESS_DIALOG + (xfer_info->progress_dialog)); + dfos_xfer_progress_dialog_set_operation_string + (DFOS_XFER_PROGRESS_DIALOG + (xfer_info->progress_dialog), + xfer_info->cleanup_name); + } + return TRUE; + case GNOME_VFS_XFER_PHASE_COMPLETED: nautilus_file_changes_consume_changes (TRUE); if (xfer_info->progress_dialog != NULL) { @@ -204,15 +230,18 @@ handle_xfer_vfs_error (const GnomeVFSXferProgressInfo *progress_info, int result; char *text; + char *unescaped_name; switch (xfer_info->error_mode) { case GNOME_VFS_XFER_ERROR_MODE_QUERY: + unescaped_name = gnome_vfs_unescape_string_for_display (progress_info->source_name); /* transfer error, prompt the user to continue or stop */ text = g_strdup_printf ( _("Error %s copying file %s.\n" "Would you like to continue?"), gnome_vfs_result_to_string (progress_info->vfs_status), - progress_info->source_name); + unescaped_name); + g_free (unescaped_name); result = nautilus_simple_dialog (xfer_info->parent_view, text, _("File copy error"), @@ -247,10 +276,13 @@ handle_xfer_overwrite (const GnomeVFSXferProgressInfo *progress_info, /* transfer conflict, prompt the user to replace or skip */ int result; char *text; + char *unescaped_name; + unescaped_name = gnome_vfs_unescape_string_for_display (progress_info->target_name); text = g_strdup_printf ( _("File %s already exists.\n" "Would you like to replace it?"), - progress_info->target_name); + unescaped_name); + g_free (unescaped_name); if (progress_info->duplicate_count == 1) { /* we are going to only get one duplicate alert, don't offer @@ -358,7 +390,6 @@ sync_xfer_callback (GnomeVFSXferProgressInfo *progress_info, gpointer data) return 1; } - void dfos_xfer (DFOS *dfos, const gchar *source_directory_uri, @@ -452,6 +483,7 @@ fs_xfer (const GList *item_uris, XferInfo *xfer_info; char *target_dir_uri_text; GnomeVFSResult result; + gboolean same_fs; g_assert (item_uris != NULL); @@ -482,6 +514,12 @@ fs_xfer (const GList *item_uris, move_options |= GNOME_VFS_XFER_REMOVESOURCE; } + same_fs = TRUE; + if (source_dir_uri != NULL && target_dir_uri != NULL) { + gnome_vfs_check_same_fs_uris (source_dir_uri, + target_dir_uri, &same_fs); + } + /* set up the copy/move parameters */ xfer_info = g_new (XferInfo, 1); xfer_info->parent_view = view; @@ -490,14 +528,17 @@ fs_xfer (const GList *item_uris, if ((move_options & GNOME_VFS_XFER_REMOVESOURCE) != 0) { xfer_info->operation_name = _("Moving"); xfer_info->preparation_name =_("Preparing To Move..."); + xfer_info->cleanup_name =_("Finishing Move..."); xfer_info->kind = XFER_MOVE; /* Do an arbitrary guess that an operation will take very little * time and the progress shouldn't be shown. */ - xfer_info->show_progress_dialog = g_list_length ((GList *)item_uris) > 20; + xfer_info->show_progress_dialog = + !same_fs || g_list_length ((GList *)item_uris) > 20; } else { xfer_info->operation_name = _("Copying"); xfer_info->preparation_name =_("Preparing To Copy..."); + xfer_info->cleanup_name =_("Finishing Copy..."); xfer_info->kind = XFER_COPY; /* always show progress during copy */ xfer_info->show_progress_dialog = TRUE; @@ -574,7 +615,9 @@ fs_xfer (const GList *item_uris, g_free (target_dir_uri_text); - gnome_vfs_uri_unref (trash_dir_uri); + if (trash_dir_uri != NULL) { + gnome_vfs_uri_unref (trash_dir_uri); + } gnome_vfs_uri_unref (target_dir_uri); gnome_vfs_uri_unref (source_dir_uri); nautilus_g_list_free_deep (item_names); @@ -681,7 +724,8 @@ fs_move_to_trash (const GList *item_uris, GtkWidget *parent_view) _("OK"), NULL, NULL); bail = TRUE; } else if (gnome_vfs_uri_is_parent (uri, trash_dir_uri, TRUE)) { - item_name = gnome_vfs_uri_extract_short_name (uri); + item_name = nautilus_convert_to_unescaped_string_for_display + (gnome_vfs_uri_extract_short_name (uri)); text = g_strdup_printf ( _("You cannot throw \"%s\" " "into the Trash."), item_name); @@ -716,6 +760,7 @@ fs_move_to_trash (const GList *item_uris, GtkWidget *parent_view) xfer_info->operation_name = _("Moving to Trash"); xfer_info->preparation_name =_("Preparing to Move to Trash..."); + xfer_info->cleanup_name =_("Finishing Move to Trash..."); xfer_info->error_mode = GNOME_VFS_XFER_ERROR_MODE_QUERY; xfer_info->overwrite_mode = GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE; xfer_info->kind = XFER_MOVE_TO_TRASH; @@ -756,6 +801,7 @@ fs_delete (const GList *item_uris, GtkWidget *parent_view) xfer_info->show_progress_dialog = TRUE; xfer_info->operation_name = _("Deleting"); xfer_info->preparation_name =_("Preparing to Delete..."); + xfer_info->cleanup_name =_("Finishing Delete..."); xfer_info->error_mode = GNOME_VFS_XFER_ERROR_MODE_QUERY; xfer_info->overwrite_mode = GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE; xfer_info->kind = XFER_DELETE; @@ -801,6 +847,7 @@ fs_empty_trash (GtkWidget *parent_view) xfer_info->show_progress_dialog = TRUE; xfer_info->operation_name = _("Emptying the Trash"); xfer_info->preparation_name =_("Preparing to Empty the Trash..."); + xfer_info->cleanup_name =_("Finishing Emptying the Trash..."); xfer_info->error_mode = GNOME_VFS_XFER_ERROR_MODE_QUERY; xfer_info->overwrite_mode = GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE; xfer_info->kind = XFER_EMPTY_TRASH; diff --git a/libnautilus-extensions/nautilus-file-operations.h b/libnautilus-extensions/nautilus-file-operations.h index 9e9de244d..d9b207d95 100644 --- a/libnautilus-extensions/nautilus-file-operations.h +++ b/libnautilus-extensions/nautilus-file-operations.h @@ -52,4 +52,9 @@ void fs_new_folder (GtkWidget *parent_view, gpointer data); void fs_delete (const GList *item_uris, GtkWidget *parent_view); + +/* Prepare an escaped string for display. Unescapes a string in place. + * Frees the original string. + */ +char *nautilus_convert_to_unescaped_string_for_display (char *escaped); #endif /* DFOS_XFER_H */ diff --git a/libnautilus-extensions/nautilus-icon-dnd.c b/libnautilus-extensions/nautilus-icon-dnd.c index a0bd0462b..db7d8617b 100644 --- a/libnautilus-extensions/nautilus-icon-dnd.c +++ b/libnautilus-extensions/nautilus-icon-dnd.c @@ -590,10 +590,10 @@ static void handle_nonlocal_move (NautilusIconContainer *container, GdkDragContext *context, int x, int y, - NautilusIcon *drop_target_icon) + const char *target_uri, + gboolean icon_hit) { GList *source_uris, *p; - char *target_uri; GdkPoint *source_item_locations; int i; @@ -609,7 +609,7 @@ handle_nonlocal_move (NautilusIconContainer *container, source_uris = g_list_reverse (source_uris); source_item_locations = NULL; - if (drop_target_icon != NULL) { + if (!icon_hit) { /* Drop onto a container. Pass along the item points to allow placing * the items in their same relative positions in the new container. */ @@ -623,15 +623,7 @@ handle_nonlocal_move (NautilusIconContainer *container, source_item_locations[i].y = ((DragSelectionItem *)p->data)->icon_y; } } - - /* get the URI of either the item or the container we hit */ - if (drop_target_icon != NULL) { - target_uri = nautilus_icon_container_get_icon_uri - (container, drop_target_icon); - } else { - target_uri = get_container_uri (container); - } - + /* start the copy */ gtk_signal_emit_by_name (GTK_OBJECT (container), "move_copy_items", source_uris, @@ -641,20 +633,19 @@ handle_nonlocal_move (NautilusIconContainer *container, x, y); g_list_free (source_uris); g_free (source_item_locations); - g_free (target_uri); } -static void -nautilus_icon_container_receive_dropped_icons (NautilusIconContainer *container, - GdkDragContext *context, - int x, int y) +static char * +nautilus_icon_container_find_drop_target (NautilusIconContainer *container, + GdkDragContext *context, + int x, int y, + gboolean *icon_hit) { NautilusIcon *drop_target_icon; - gboolean local_move_only; double world_x, world_y; - + if (container->details->dnd_info->drag_info.selection_list == NULL) { - return; + return NULL; } gnome_canvas_window_to_world (GNOME_CANVAS (container), @@ -679,8 +670,38 @@ nautilus_icon_container_receive_dropped_icons (NautilusIconContainer *container, drop_target_icon = NULL; } + if (!drop_target_icon) { + *icon_hit = FALSE; + return get_container_uri (container); + } + + + *icon_hit = TRUE; + return nautilus_icon_container_get_icon_uri (container, drop_target_icon); +} + +static void +nautilus_icon_container_receive_dropped_icons (NautilusIconContainer *container, + GdkDragContext *context, + int x, int y) +{ + char *drop_target; + gboolean local_move_only; + double world_x, world_y; + gboolean icon_hit; + + if (container->details->dnd_info->drag_info.selection_list == NULL) { + return; + } + + gnome_canvas_window_to_world (GNOME_CANVAS (container), + x, y, &world_x, &world_y); + + drop_target = nautilus_icon_container_find_drop_target (container, + context, x, y, &icon_hit); + local_move_only = FALSE; - if (drop_target_icon == NULL && context->action == GDK_ACTION_MOVE) { + if (!icon_hit && context->action == GDK_ACTION_MOVE) { /* we can just move the icon positions if the move ended up in * the item's parent container */ @@ -691,14 +712,45 @@ nautilus_icon_container_receive_dropped_icons (NautilusIconContainer *container, if (local_move_only) { handle_local_move (container, world_x, world_y); } else { - handle_nonlocal_move (container, context, x, y, drop_target_icon); + handle_nonlocal_move (container, context, x, y, drop_target, icon_hit); } + g_free (drop_target); nautilus_drag_destroy_selection_list (container->details->dnd_info->drag_info.selection_list); container->details->dnd_info->drag_info.selection_list = NULL; } static void +nautilus_icon_container_get_drop_action (NautilusIconContainer *container, + GdkDragContext *context, + int x, int y, + int *default_action, + int *non_default_action) +{ + char *drop_target; + gboolean icon_hit; + + if (container->details->dnd_info->drag_info.selection_list == NULL) { + *default_action = 0; + *non_default_action = 0; + return; + } + + drop_target = nautilus_icon_container_find_drop_target (container, + context, x, y, &icon_hit); + + if (!drop_target) { + *default_action = 0; + *non_default_action = 0; + return; + } + + nautilus_drag_default_drop_action (drop_target, + container->details->dnd_info->drag_info.selection_list, default_action, non_default_action); + g_free (drop_target); +} + +static void set_drop_target (NautilusIconContainer *container, NautilusIcon *icon) { @@ -927,11 +979,22 @@ drag_motion_callback (GtkWidget *widget, int x, int y, guint32 time) { + int default_action, non_default_action; + nautilus_icon_container_ensure_drag_data (NAUTILUS_ICON_CONTAINER (widget), context, time); nautilus_icon_container_position_shadow (NAUTILUS_ICON_CONTAINER (widget), x, y); nautilus_icon_dnd_update_drop_target (NAUTILUS_ICON_CONTAINER (widget), context, x, y); - gdk_drag_status (context, nautilus_drag_modifier_based_action (), time); + /* Find out what the drop actions are based on our drag selection and + * the drop target. + */ + nautilus_icon_container_get_drop_action (NAUTILUS_ICON_CONTAINER (widget), context, x, y, + &default_action, &non_default_action); + + /* set the right drop action, choose based on modifier key state + */ + gdk_drag_status (context, nautilus_drag_modifier_based_action (default_action, + non_default_action), time); return TRUE; } diff --git a/libnautilus-extensions/nautilus-list.c b/libnautilus-extensions/nautilus-list.c index 8c6c9c45d..c111e2bd7 100644 --- a/libnautilus-extensions/nautilus-list.c +++ b/libnautilus-extensions/nautilus-list.c @@ -2463,7 +2463,12 @@ nautilus_list_drag_motion (GtkWidget *widget, GdkDragContext *context, { NautilusList *list; - gdk_drag_status (context, nautilus_drag_modifier_based_action (), time); + /* FIXME: + * pass in the drop action default and non-default values here based on + * the drag selection and drop target + */ + gdk_drag_status (context, nautilus_drag_modifier_based_action (GDK_ACTION_MOVE, + GDK_ACTION_COPY), time); g_assert (NAUTILUS_IS_LIST (widget)); list = NAUTILUS_LIST (widget); diff --git a/libnautilus-private/nautilus-drag.c b/libnautilus-private/nautilus-drag.c index 6b16298cf..b05d55074 100644 --- a/libnautilus-private/nautilus-drag.c +++ b/libnautilus-private/nautilus-drag.c @@ -27,6 +27,7 @@ #include <libgnomevfs/gnome-vfs-types.h> #include <libgnomevfs/gnome-vfs-uri.h> +#include <libgnomevfs/gnome-vfs-ops.h> #include <string.h> #include <stdio.h> @@ -242,6 +243,37 @@ nautilus_drag_can_accept_items (NautilusFile *drop_target_item, return TRUE; } +void +nautilus_drag_default_drop_action (const char *target_uri_string, const GList *items, + int *default_action, int *non_default_action) +{ + gboolean same_fs; + GnomeVFSURI *target_uri; + GnomeVFSURI *dropped_uri; + + if (target_uri_string == NULL) { + *default_action = 0; + *non_default_action = 0; + return; + } + + target_uri = gnome_vfs_uri_new (target_uri_string); + + /* Compare the first dropped uri with the target uri for same fs match. */ + dropped_uri = gnome_vfs_uri_new (((DragSelectionItem *)items->data)->uri); + same_fs = TRUE; + gnome_vfs_check_same_fs_uris (target_uri, dropped_uri, &same_fs); + gnome_vfs_uri_unref (dropped_uri); + gnome_vfs_uri_unref (target_uri); + + if (same_fs) { + *default_action = GDK_ACTION_MOVE; + *non_default_action = GDK_ACTION_COPY; + } else { + *default_action = GDK_ACTION_COPY; + *non_default_action = GDK_ACTION_MOVE; + } +} /* Encode a "x-special/gnome-icon-list" selection. Along with the URIs of the dragged files, this encodes @@ -311,17 +343,17 @@ nautilus_drag_drag_data_get (GtkWidget *widget, } int -nautilus_drag_modifier_based_action () +nautilus_drag_modifier_based_action (int default_action, int non_default_action) { GdkModifierType modifiers; gdk_window_get_pointer (NULL, NULL, NULL, &modifiers); if ((modifiers & GDK_CONTROL_MASK) != 0) { - return GDK_ACTION_COPY; + return non_default_action; } else if ((modifiers & GDK_MOD1_MASK) != 0) { return GDK_ACTION_LINK; } - return GDK_ACTION_MOVE; + return default_action; } diff --git a/libnautilus-private/nautilus-drag.h b/libnautilus-private/nautilus-drag.h index 702743fba..c6452155a 100644 --- a/libnautilus-private/nautilus-drag.h +++ b/libnautilus-private/nautilus-drag.h @@ -102,6 +102,10 @@ gboolean nautilus_drag_can_accept_item (NautilusFile *drop_target_item, const char *item_uri); gboolean nautilus_drag_can_accept_items (NautilusFile *drop_target_item, const GList *items); +void nautilus_drag_default_drop_action (const char *target_uri, + const GList *items, + int *default_action, + int *non_default_action); gboolean nautilus_drag_drag_data_get (GtkWidget *widget, GdkDragContext *context, @@ -110,6 +114,7 @@ gboolean nautilus_drag_drag_data_get (GtkWidget *widget, guint32 time, gpointer container_context, NautilusDragEachSelectedItemIterator each_selected_item_iterator); -int nautilus_drag_modifier_based_action (void); +int nautilus_drag_modifier_based_action (int default_action, + int non_default_action); #endif diff --git a/libnautilus-private/nautilus-file-operations-progress.c b/libnautilus-private/nautilus-file-operations-progress.c index 093eab029..1ccd468e6 100644 --- a/libnautilus-private/nautilus-file-operations-progress.c +++ b/libnautilus-private/nautilus-file-operations-progress.c @@ -19,9 +19,13 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - Author: Ettore Perazzoli <ettore@gnu.org> */ + Authors: + Ettore Perazzoli <ettore@gnu.org> + Pavel Cisler <pavel@eazel.com> + */ #include <config.h> +#include <libgnomevfs/gnome-vfs-utils.h> #include "dfos-xfer-progress-dialog.h" #include <gnome.h> @@ -79,49 +83,61 @@ trim_string (const char *string, } static void -set_text_trimmed (GtkLabel *label, - const char *text, - const char *trimmable_text, - guint max_width) +set_text_unescaped_trimmed (GtkLabel *label, + const char *text, + const char *trimmable_text, + guint max_width) { GdkFont *font; + char *unescaped_text; char *trimmed_text; + char *unescaped_trimmable_text; char *s; guint text_width; guint trimmable_text_width; font = GTK_WIDGET (label)->style->font; - if (text != NULL) - text_width = gdk_string_width (font, text); - else + trimmed_text = NULL; + unescaped_text = NULL; + unescaped_trimmable_text = NULL; + + if (text) { + unescaped_text = gnome_vfs_unescape_string_for_display (text); + } + if (trimmable_text) { + unescaped_trimmable_text = gnome_vfs_unescape_string_for_display (trimmable_text); + } + + if (unescaped_text != NULL) { + text_width = gdk_string_width (font, unescaped_text); + } else { text_width = 0; + } - if (trimmable_text != NULL) - trimmable_text_width = gdk_string_width (font, trimmable_text); + if (unescaped_trimmable_text != NULL) + trimmable_text_width = gdk_string_width (font, unescaped_trimmable_text); else trimmable_text_width = 0; if (text_width + trimmable_text_width <= max_width) { - s = g_strconcat (text, trimmable_text, NULL); - gtk_label_set_text (GTK_LABEL (label), s); - g_free (s); - return; + s = g_strconcat (unescaped_text, unescaped_trimmable_text, NULL); + } else { + + trimmed_text = trim_string (unescaped_trimmable_text, + font, + max_width - text_width, + trimmable_text_width); + s = g_strconcat (unescaped_text, trimmed_text, NULL); } - trimmed_text = trim_string (trimmable_text, - font, - max_width - text_width, - trimmable_text_width); - s = g_strconcat (text, trimmed_text, NULL); - gtk_label_set_text (GTK_LABEL (label), s); - g_free (s); g_free (trimmed_text); + g_free (unescaped_text); + g_free (unescaped_trimmable_text); } - /* GnomeDialog signals. */ /* This is just to make sure the dialog is not closed without explicit @@ -135,7 +151,6 @@ do_close (GnomeDialog *dialog) return FALSE; } - /* GtkObject methods. */ static void @@ -148,7 +163,6 @@ destroy (GtkObject *object) g_free (dialog->operation_string); } - /* Initialization. */ static GtkWidget * @@ -215,7 +229,6 @@ class_init (DFOSXferProgressDialogClass *class) dialog_class->close = do_close; } - /* Public functions. */ guint @@ -320,20 +333,30 @@ dfos_xfer_progress_dialog_new_file (DFOSXferProgressDialog *dialog, gtk_label_set_text (GTK_LABEL (dialog->operation_label), s); g_free (s); - set_text_trimmed (GTK_LABEL (dialog->source_label), - dialog->from_prefix, source_uri, - DIALOG_WIDTH); + set_text_unescaped_trimmed (GTK_LABEL (dialog->source_label), + dialog->from_prefix, source_uri, DIALOG_WIDTH); if (dialog->to_prefix != NULL && dialog->target_label != NULL) - set_text_trimmed (GTK_LABEL (dialog->target_label), - dialog->to_prefix, target_uri, - DIALOG_WIDTH); + set_text_unescaped_trimmed (GTK_LABEL (dialog->target_label), + dialog->to_prefix, target_uri, DIALOG_WIDTH); update (dialog); } void +dfos_xfer_progress_dialog_clear (DFOSXferProgressDialog *dialog) +{ + gtk_label_set_text (GTK_LABEL (dialog->source_label), ""); + gtk_label_set_text (GTK_LABEL (dialog->target_label), ""); + + dialog->files_total = 0; + dialog->bytes_total = 0; + + update (dialog); +} + +void dfos_xfer_progress_dialog_update (DFOSXferProgressDialog *dialog, gulong bytes_done_in_file, gulong bytes_done) @@ -346,7 +369,6 @@ dfos_xfer_progress_dialog_update (DFOSXferProgressDialog *dialog, update (dialog); } - void dfos_xfer_progress_dialog_freeze (DFOSXferProgressDialog *dialog) { diff --git a/libnautilus-private/nautilus-file-operations-progress.h b/libnautilus-private/nautilus-file-operations-progress.h index e96e719ca..6ff75cb16 100644 --- a/libnautilus-private/nautilus-file-operations-progress.h +++ b/libnautilus-private/nautilus-file-operations-progress.h @@ -86,6 +86,9 @@ void dfos_xfer_progress_dialog_set_operation_string (DFOSXferProgressDialog *dialog, const char *operation_string); +void dfos_xfer_progress_dialog_clear + (DFOSXferProgressDialog *dialog); + void dfos_xfer_progress_dialog_new_file (DFOSXferProgressDialog *dialog, const char *source_uri, diff --git a/libnautilus-private/nautilus-file-operations.c b/libnautilus-private/nautilus-file-operations.c index 38361d331..5c1ea82be 100644 --- a/libnautilus-private/nautilus-file-operations.c +++ b/libnautilus-private/nautilus-file-operations.c @@ -42,12 +42,12 @@ typedef enum { XFER_DELETE } XferKind; - typedef struct XferInfo { GnomeVFSAsyncHandle *handle; GtkWidget *progress_dialog; const char *operation_name; const char *preparation_name; + const char *cleanup_name; GnomeVFSXferErrorMode error_mode; GnomeVFSXferOverwriteMode overwrite_mode; GtkWidget *parent_view; @@ -75,6 +75,19 @@ xfer_info_new (GnomeVFSAsyncHandle *handle, return info; } +char * +nautilus_convert_to_unescaped_string_for_display (char *escaped) +{ + char *result; + if (!escaped) { + return NULL; + } + result = gnome_vfs_unescape_string_for_display (escaped); + g_free (escaped); + return result; +} + + static void xfer_dialog_clicked_callback (DFOSXferProgressDialog *dialog, int button_number, @@ -153,6 +166,7 @@ handle_xfer_ok (const GnomeVFSXferProgressInfo *progress_info, case GNOME_VFS_XFER_PHASE_COPYING: if (xfer_info->progress_dialog != NULL) { + if (progress_info->bytes_copied == 0) { dfos_xfer_progress_dialog_new_file (DFOS_XFER_PROGRESS_DIALOG @@ -181,6 +195,18 @@ handle_xfer_ok (const GnomeVFSXferProgressInfo *progress_info, } return TRUE; + case GNOME_VFS_XFER_PHASE_CLEANUP: + if (xfer_info->progress_dialog != NULL) { + dfos_xfer_progress_dialog_clear( + DFOS_XFER_PROGRESS_DIALOG + (xfer_info->progress_dialog)); + dfos_xfer_progress_dialog_set_operation_string + (DFOS_XFER_PROGRESS_DIALOG + (xfer_info->progress_dialog), + xfer_info->cleanup_name); + } + return TRUE; + case GNOME_VFS_XFER_PHASE_COMPLETED: nautilus_file_changes_consume_changes (TRUE); if (xfer_info->progress_dialog != NULL) { @@ -204,15 +230,18 @@ handle_xfer_vfs_error (const GnomeVFSXferProgressInfo *progress_info, int result; char *text; + char *unescaped_name; switch (xfer_info->error_mode) { case GNOME_VFS_XFER_ERROR_MODE_QUERY: + unescaped_name = gnome_vfs_unescape_string_for_display (progress_info->source_name); /* transfer error, prompt the user to continue or stop */ text = g_strdup_printf ( _("Error %s copying file %s.\n" "Would you like to continue?"), gnome_vfs_result_to_string (progress_info->vfs_status), - progress_info->source_name); + unescaped_name); + g_free (unescaped_name); result = nautilus_simple_dialog (xfer_info->parent_view, text, _("File copy error"), @@ -247,10 +276,13 @@ handle_xfer_overwrite (const GnomeVFSXferProgressInfo *progress_info, /* transfer conflict, prompt the user to replace or skip */ int result; char *text; + char *unescaped_name; + unescaped_name = gnome_vfs_unescape_string_for_display (progress_info->target_name); text = g_strdup_printf ( _("File %s already exists.\n" "Would you like to replace it?"), - progress_info->target_name); + unescaped_name); + g_free (unescaped_name); if (progress_info->duplicate_count == 1) { /* we are going to only get one duplicate alert, don't offer @@ -358,7 +390,6 @@ sync_xfer_callback (GnomeVFSXferProgressInfo *progress_info, gpointer data) return 1; } - void dfos_xfer (DFOS *dfos, const gchar *source_directory_uri, @@ -452,6 +483,7 @@ fs_xfer (const GList *item_uris, XferInfo *xfer_info; char *target_dir_uri_text; GnomeVFSResult result; + gboolean same_fs; g_assert (item_uris != NULL); @@ -482,6 +514,12 @@ fs_xfer (const GList *item_uris, move_options |= GNOME_VFS_XFER_REMOVESOURCE; } + same_fs = TRUE; + if (source_dir_uri != NULL && target_dir_uri != NULL) { + gnome_vfs_check_same_fs_uris (source_dir_uri, + target_dir_uri, &same_fs); + } + /* set up the copy/move parameters */ xfer_info = g_new (XferInfo, 1); xfer_info->parent_view = view; @@ -490,14 +528,17 @@ fs_xfer (const GList *item_uris, if ((move_options & GNOME_VFS_XFER_REMOVESOURCE) != 0) { xfer_info->operation_name = _("Moving"); xfer_info->preparation_name =_("Preparing To Move..."); + xfer_info->cleanup_name =_("Finishing Move..."); xfer_info->kind = XFER_MOVE; /* Do an arbitrary guess that an operation will take very little * time and the progress shouldn't be shown. */ - xfer_info->show_progress_dialog = g_list_length ((GList *)item_uris) > 20; + xfer_info->show_progress_dialog = + !same_fs || g_list_length ((GList *)item_uris) > 20; } else { xfer_info->operation_name = _("Copying"); xfer_info->preparation_name =_("Preparing To Copy..."); + xfer_info->cleanup_name =_("Finishing Copy..."); xfer_info->kind = XFER_COPY; /* always show progress during copy */ xfer_info->show_progress_dialog = TRUE; @@ -574,7 +615,9 @@ fs_xfer (const GList *item_uris, g_free (target_dir_uri_text); - gnome_vfs_uri_unref (trash_dir_uri); + if (trash_dir_uri != NULL) { + gnome_vfs_uri_unref (trash_dir_uri); + } gnome_vfs_uri_unref (target_dir_uri); gnome_vfs_uri_unref (source_dir_uri); nautilus_g_list_free_deep (item_names); @@ -681,7 +724,8 @@ fs_move_to_trash (const GList *item_uris, GtkWidget *parent_view) _("OK"), NULL, NULL); bail = TRUE; } else if (gnome_vfs_uri_is_parent (uri, trash_dir_uri, TRUE)) { - item_name = gnome_vfs_uri_extract_short_name (uri); + item_name = nautilus_convert_to_unescaped_string_for_display + (gnome_vfs_uri_extract_short_name (uri)); text = g_strdup_printf ( _("You cannot throw \"%s\" " "into the Trash."), item_name); @@ -716,6 +760,7 @@ fs_move_to_trash (const GList *item_uris, GtkWidget *parent_view) xfer_info->operation_name = _("Moving to Trash"); xfer_info->preparation_name =_("Preparing to Move to Trash..."); + xfer_info->cleanup_name =_("Finishing Move to Trash..."); xfer_info->error_mode = GNOME_VFS_XFER_ERROR_MODE_QUERY; xfer_info->overwrite_mode = GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE; xfer_info->kind = XFER_MOVE_TO_TRASH; @@ -756,6 +801,7 @@ fs_delete (const GList *item_uris, GtkWidget *parent_view) xfer_info->show_progress_dialog = TRUE; xfer_info->operation_name = _("Deleting"); xfer_info->preparation_name =_("Preparing to Delete..."); + xfer_info->cleanup_name =_("Finishing Delete..."); xfer_info->error_mode = GNOME_VFS_XFER_ERROR_MODE_QUERY; xfer_info->overwrite_mode = GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE; xfer_info->kind = XFER_DELETE; @@ -801,6 +847,7 @@ fs_empty_trash (GtkWidget *parent_view) xfer_info->show_progress_dialog = TRUE; xfer_info->operation_name = _("Emptying the Trash"); xfer_info->preparation_name =_("Preparing to Empty the Trash..."); + xfer_info->cleanup_name =_("Finishing Emptying the Trash..."); xfer_info->error_mode = GNOME_VFS_XFER_ERROR_MODE_QUERY; xfer_info->overwrite_mode = GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE; xfer_info->kind = XFER_EMPTY_TRASH; diff --git a/libnautilus-private/nautilus-file-operations.h b/libnautilus-private/nautilus-file-operations.h index 9e9de244d..d9b207d95 100644 --- a/libnautilus-private/nautilus-file-operations.h +++ b/libnautilus-private/nautilus-file-operations.h @@ -52,4 +52,9 @@ void fs_new_folder (GtkWidget *parent_view, gpointer data); void fs_delete (const GList *item_uris, GtkWidget *parent_view); + +/* Prepare an escaped string for display. Unescapes a string in place. + * Frees the original string. + */ +char *nautilus_convert_to_unescaped_string_for_display (char *escaped); #endif /* DFOS_XFER_H */ diff --git a/libnautilus-private/nautilus-icon-dnd.c b/libnautilus-private/nautilus-icon-dnd.c index a0bd0462b..db7d8617b 100644 --- a/libnautilus-private/nautilus-icon-dnd.c +++ b/libnautilus-private/nautilus-icon-dnd.c @@ -590,10 +590,10 @@ static void handle_nonlocal_move (NautilusIconContainer *container, GdkDragContext *context, int x, int y, - NautilusIcon *drop_target_icon) + const char *target_uri, + gboolean icon_hit) { GList *source_uris, *p; - char *target_uri; GdkPoint *source_item_locations; int i; @@ -609,7 +609,7 @@ handle_nonlocal_move (NautilusIconContainer *container, source_uris = g_list_reverse (source_uris); source_item_locations = NULL; - if (drop_target_icon != NULL) { + if (!icon_hit) { /* Drop onto a container. Pass along the item points to allow placing * the items in their same relative positions in the new container. */ @@ -623,15 +623,7 @@ handle_nonlocal_move (NautilusIconContainer *container, source_item_locations[i].y = ((DragSelectionItem *)p->data)->icon_y; } } - - /* get the URI of either the item or the container we hit */ - if (drop_target_icon != NULL) { - target_uri = nautilus_icon_container_get_icon_uri - (container, drop_target_icon); - } else { - target_uri = get_container_uri (container); - } - + /* start the copy */ gtk_signal_emit_by_name (GTK_OBJECT (container), "move_copy_items", source_uris, @@ -641,20 +633,19 @@ handle_nonlocal_move (NautilusIconContainer *container, x, y); g_list_free (source_uris); g_free (source_item_locations); - g_free (target_uri); } -static void -nautilus_icon_container_receive_dropped_icons (NautilusIconContainer *container, - GdkDragContext *context, - int x, int y) +static char * +nautilus_icon_container_find_drop_target (NautilusIconContainer *container, + GdkDragContext *context, + int x, int y, + gboolean *icon_hit) { NautilusIcon *drop_target_icon; - gboolean local_move_only; double world_x, world_y; - + if (container->details->dnd_info->drag_info.selection_list == NULL) { - return; + return NULL; } gnome_canvas_window_to_world (GNOME_CANVAS (container), @@ -679,8 +670,38 @@ nautilus_icon_container_receive_dropped_icons (NautilusIconContainer *container, drop_target_icon = NULL; } + if (!drop_target_icon) { + *icon_hit = FALSE; + return get_container_uri (container); + } + + + *icon_hit = TRUE; + return nautilus_icon_container_get_icon_uri (container, drop_target_icon); +} + +static void +nautilus_icon_container_receive_dropped_icons (NautilusIconContainer *container, + GdkDragContext *context, + int x, int y) +{ + char *drop_target; + gboolean local_move_only; + double world_x, world_y; + gboolean icon_hit; + + if (container->details->dnd_info->drag_info.selection_list == NULL) { + return; + } + + gnome_canvas_window_to_world (GNOME_CANVAS (container), + x, y, &world_x, &world_y); + + drop_target = nautilus_icon_container_find_drop_target (container, + context, x, y, &icon_hit); + local_move_only = FALSE; - if (drop_target_icon == NULL && context->action == GDK_ACTION_MOVE) { + if (!icon_hit && context->action == GDK_ACTION_MOVE) { /* we can just move the icon positions if the move ended up in * the item's parent container */ @@ -691,14 +712,45 @@ nautilus_icon_container_receive_dropped_icons (NautilusIconContainer *container, if (local_move_only) { handle_local_move (container, world_x, world_y); } else { - handle_nonlocal_move (container, context, x, y, drop_target_icon); + handle_nonlocal_move (container, context, x, y, drop_target, icon_hit); } + g_free (drop_target); nautilus_drag_destroy_selection_list (container->details->dnd_info->drag_info.selection_list); container->details->dnd_info->drag_info.selection_list = NULL; } static void +nautilus_icon_container_get_drop_action (NautilusIconContainer *container, + GdkDragContext *context, + int x, int y, + int *default_action, + int *non_default_action) +{ + char *drop_target; + gboolean icon_hit; + + if (container->details->dnd_info->drag_info.selection_list == NULL) { + *default_action = 0; + *non_default_action = 0; + return; + } + + drop_target = nautilus_icon_container_find_drop_target (container, + context, x, y, &icon_hit); + + if (!drop_target) { + *default_action = 0; + *non_default_action = 0; + return; + } + + nautilus_drag_default_drop_action (drop_target, + container->details->dnd_info->drag_info.selection_list, default_action, non_default_action); + g_free (drop_target); +} + +static void set_drop_target (NautilusIconContainer *container, NautilusIcon *icon) { @@ -927,11 +979,22 @@ drag_motion_callback (GtkWidget *widget, int x, int y, guint32 time) { + int default_action, non_default_action; + nautilus_icon_container_ensure_drag_data (NAUTILUS_ICON_CONTAINER (widget), context, time); nautilus_icon_container_position_shadow (NAUTILUS_ICON_CONTAINER (widget), x, y); nautilus_icon_dnd_update_drop_target (NAUTILUS_ICON_CONTAINER (widget), context, x, y); - gdk_drag_status (context, nautilus_drag_modifier_based_action (), time); + /* Find out what the drop actions are based on our drag selection and + * the drop target. + */ + nautilus_icon_container_get_drop_action (NAUTILUS_ICON_CONTAINER (widget), context, x, y, + &default_action, &non_default_action); + + /* set the right drop action, choose based on modifier key state + */ + gdk_drag_status (context, nautilus_drag_modifier_based_action (default_action, + non_default_action), time); return TRUE; } diff --git a/libnautilus-private/nautilus-list.c b/libnautilus-private/nautilus-list.c index 8c6c9c45d..c111e2bd7 100644 --- a/libnautilus-private/nautilus-list.c +++ b/libnautilus-private/nautilus-list.c @@ -2463,7 +2463,12 @@ nautilus_list_drag_motion (GtkWidget *widget, GdkDragContext *context, { NautilusList *list; - gdk_drag_status (context, nautilus_drag_modifier_based_action (), time); + /* FIXME: + * pass in the drop action default and non-default values here based on + * the drag selection and drop target + */ + gdk_drag_status (context, nautilus_drag_modifier_based_action (GDK_ACTION_MOVE, + GDK_ACTION_COPY), time); g_assert (NAUTILUS_IS_LIST (widget)); list = NAUTILUS_LIST (widget); diff --git a/src/file-manager/dfos-xfer-progress-dialog.c b/src/file-manager/dfos-xfer-progress-dialog.c index 093eab029..1ccd468e6 100644 --- a/src/file-manager/dfos-xfer-progress-dialog.c +++ b/src/file-manager/dfos-xfer-progress-dialog.c @@ -19,9 +19,13 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - Author: Ettore Perazzoli <ettore@gnu.org> */ + Authors: + Ettore Perazzoli <ettore@gnu.org> + Pavel Cisler <pavel@eazel.com> + */ #include <config.h> +#include <libgnomevfs/gnome-vfs-utils.h> #include "dfos-xfer-progress-dialog.h" #include <gnome.h> @@ -79,49 +83,61 @@ trim_string (const char *string, } static void -set_text_trimmed (GtkLabel *label, - const char *text, - const char *trimmable_text, - guint max_width) +set_text_unescaped_trimmed (GtkLabel *label, + const char *text, + const char *trimmable_text, + guint max_width) { GdkFont *font; + char *unescaped_text; char *trimmed_text; + char *unescaped_trimmable_text; char *s; guint text_width; guint trimmable_text_width; font = GTK_WIDGET (label)->style->font; - if (text != NULL) - text_width = gdk_string_width (font, text); - else + trimmed_text = NULL; + unescaped_text = NULL; + unescaped_trimmable_text = NULL; + + if (text) { + unescaped_text = gnome_vfs_unescape_string_for_display (text); + } + if (trimmable_text) { + unescaped_trimmable_text = gnome_vfs_unescape_string_for_display (trimmable_text); + } + + if (unescaped_text != NULL) { + text_width = gdk_string_width (font, unescaped_text); + } else { text_width = 0; + } - if (trimmable_text != NULL) - trimmable_text_width = gdk_string_width (font, trimmable_text); + if (unescaped_trimmable_text != NULL) + trimmable_text_width = gdk_string_width (font, unescaped_trimmable_text); else trimmable_text_width = 0; if (text_width + trimmable_text_width <= max_width) { - s = g_strconcat (text, trimmable_text, NULL); - gtk_label_set_text (GTK_LABEL (label), s); - g_free (s); - return; + s = g_strconcat (unescaped_text, unescaped_trimmable_text, NULL); + } else { + + trimmed_text = trim_string (unescaped_trimmable_text, + font, + max_width - text_width, + trimmable_text_width); + s = g_strconcat (unescaped_text, trimmed_text, NULL); } - trimmed_text = trim_string (trimmable_text, - font, - max_width - text_width, - trimmable_text_width); - s = g_strconcat (text, trimmed_text, NULL); - gtk_label_set_text (GTK_LABEL (label), s); - g_free (s); g_free (trimmed_text); + g_free (unescaped_text); + g_free (unescaped_trimmable_text); } - /* GnomeDialog signals. */ /* This is just to make sure the dialog is not closed without explicit @@ -135,7 +151,6 @@ do_close (GnomeDialog *dialog) return FALSE; } - /* GtkObject methods. */ static void @@ -148,7 +163,6 @@ destroy (GtkObject *object) g_free (dialog->operation_string); } - /* Initialization. */ static GtkWidget * @@ -215,7 +229,6 @@ class_init (DFOSXferProgressDialogClass *class) dialog_class->close = do_close; } - /* Public functions. */ guint @@ -320,20 +333,30 @@ dfos_xfer_progress_dialog_new_file (DFOSXferProgressDialog *dialog, gtk_label_set_text (GTK_LABEL (dialog->operation_label), s); g_free (s); - set_text_trimmed (GTK_LABEL (dialog->source_label), - dialog->from_prefix, source_uri, - DIALOG_WIDTH); + set_text_unescaped_trimmed (GTK_LABEL (dialog->source_label), + dialog->from_prefix, source_uri, DIALOG_WIDTH); if (dialog->to_prefix != NULL && dialog->target_label != NULL) - set_text_trimmed (GTK_LABEL (dialog->target_label), - dialog->to_prefix, target_uri, - DIALOG_WIDTH); + set_text_unescaped_trimmed (GTK_LABEL (dialog->target_label), + dialog->to_prefix, target_uri, DIALOG_WIDTH); update (dialog); } void +dfos_xfer_progress_dialog_clear (DFOSXferProgressDialog *dialog) +{ + gtk_label_set_text (GTK_LABEL (dialog->source_label), ""); + gtk_label_set_text (GTK_LABEL (dialog->target_label), ""); + + dialog->files_total = 0; + dialog->bytes_total = 0; + + update (dialog); +} + +void dfos_xfer_progress_dialog_update (DFOSXferProgressDialog *dialog, gulong bytes_done_in_file, gulong bytes_done) @@ -346,7 +369,6 @@ dfos_xfer_progress_dialog_update (DFOSXferProgressDialog *dialog, update (dialog); } - void dfos_xfer_progress_dialog_freeze (DFOSXferProgressDialog *dialog) { diff --git a/src/file-manager/dfos-xfer-progress-dialog.h b/src/file-manager/dfos-xfer-progress-dialog.h index e96e719ca..6ff75cb16 100644 --- a/src/file-manager/dfos-xfer-progress-dialog.h +++ b/src/file-manager/dfos-xfer-progress-dialog.h @@ -86,6 +86,9 @@ void dfos_xfer_progress_dialog_set_operation_string (DFOSXferProgressDialog *dialog, const char *operation_string); +void dfos_xfer_progress_dialog_clear + (DFOSXferProgressDialog *dialog); + void dfos_xfer_progress_dialog_new_file (DFOSXferProgressDialog *dialog, const char *source_uri, diff --git a/src/file-manager/dfos-xfer.c b/src/file-manager/dfos-xfer.c index 38361d331..5c1ea82be 100644 --- a/src/file-manager/dfos-xfer.c +++ b/src/file-manager/dfos-xfer.c @@ -42,12 +42,12 @@ typedef enum { XFER_DELETE } XferKind; - typedef struct XferInfo { GnomeVFSAsyncHandle *handle; GtkWidget *progress_dialog; const char *operation_name; const char *preparation_name; + const char *cleanup_name; GnomeVFSXferErrorMode error_mode; GnomeVFSXferOverwriteMode overwrite_mode; GtkWidget *parent_view; @@ -75,6 +75,19 @@ xfer_info_new (GnomeVFSAsyncHandle *handle, return info; } +char * +nautilus_convert_to_unescaped_string_for_display (char *escaped) +{ + char *result; + if (!escaped) { + return NULL; + } + result = gnome_vfs_unescape_string_for_display (escaped); + g_free (escaped); + return result; +} + + static void xfer_dialog_clicked_callback (DFOSXferProgressDialog *dialog, int button_number, @@ -153,6 +166,7 @@ handle_xfer_ok (const GnomeVFSXferProgressInfo *progress_info, case GNOME_VFS_XFER_PHASE_COPYING: if (xfer_info->progress_dialog != NULL) { + if (progress_info->bytes_copied == 0) { dfos_xfer_progress_dialog_new_file (DFOS_XFER_PROGRESS_DIALOG @@ -181,6 +195,18 @@ handle_xfer_ok (const GnomeVFSXferProgressInfo *progress_info, } return TRUE; + case GNOME_VFS_XFER_PHASE_CLEANUP: + if (xfer_info->progress_dialog != NULL) { + dfos_xfer_progress_dialog_clear( + DFOS_XFER_PROGRESS_DIALOG + (xfer_info->progress_dialog)); + dfos_xfer_progress_dialog_set_operation_string + (DFOS_XFER_PROGRESS_DIALOG + (xfer_info->progress_dialog), + xfer_info->cleanup_name); + } + return TRUE; + case GNOME_VFS_XFER_PHASE_COMPLETED: nautilus_file_changes_consume_changes (TRUE); if (xfer_info->progress_dialog != NULL) { @@ -204,15 +230,18 @@ handle_xfer_vfs_error (const GnomeVFSXferProgressInfo *progress_info, int result; char *text; + char *unescaped_name; switch (xfer_info->error_mode) { case GNOME_VFS_XFER_ERROR_MODE_QUERY: + unescaped_name = gnome_vfs_unescape_string_for_display (progress_info->source_name); /* transfer error, prompt the user to continue or stop */ text = g_strdup_printf ( _("Error %s copying file %s.\n" "Would you like to continue?"), gnome_vfs_result_to_string (progress_info->vfs_status), - progress_info->source_name); + unescaped_name); + g_free (unescaped_name); result = nautilus_simple_dialog (xfer_info->parent_view, text, _("File copy error"), @@ -247,10 +276,13 @@ handle_xfer_overwrite (const GnomeVFSXferProgressInfo *progress_info, /* transfer conflict, prompt the user to replace or skip */ int result; char *text; + char *unescaped_name; + unescaped_name = gnome_vfs_unescape_string_for_display (progress_info->target_name); text = g_strdup_printf ( _("File %s already exists.\n" "Would you like to replace it?"), - progress_info->target_name); + unescaped_name); + g_free (unescaped_name); if (progress_info->duplicate_count == 1) { /* we are going to only get one duplicate alert, don't offer @@ -358,7 +390,6 @@ sync_xfer_callback (GnomeVFSXferProgressInfo *progress_info, gpointer data) return 1; } - void dfos_xfer (DFOS *dfos, const gchar *source_directory_uri, @@ -452,6 +483,7 @@ fs_xfer (const GList *item_uris, XferInfo *xfer_info; char *target_dir_uri_text; GnomeVFSResult result; + gboolean same_fs; g_assert (item_uris != NULL); @@ -482,6 +514,12 @@ fs_xfer (const GList *item_uris, move_options |= GNOME_VFS_XFER_REMOVESOURCE; } + same_fs = TRUE; + if (source_dir_uri != NULL && target_dir_uri != NULL) { + gnome_vfs_check_same_fs_uris (source_dir_uri, + target_dir_uri, &same_fs); + } + /* set up the copy/move parameters */ xfer_info = g_new (XferInfo, 1); xfer_info->parent_view = view; @@ -490,14 +528,17 @@ fs_xfer (const GList *item_uris, if ((move_options & GNOME_VFS_XFER_REMOVESOURCE) != 0) { xfer_info->operation_name = _("Moving"); xfer_info->preparation_name =_("Preparing To Move..."); + xfer_info->cleanup_name =_("Finishing Move..."); xfer_info->kind = XFER_MOVE; /* Do an arbitrary guess that an operation will take very little * time and the progress shouldn't be shown. */ - xfer_info->show_progress_dialog = g_list_length ((GList *)item_uris) > 20; + xfer_info->show_progress_dialog = + !same_fs || g_list_length ((GList *)item_uris) > 20; } else { xfer_info->operation_name = _("Copying"); xfer_info->preparation_name =_("Preparing To Copy..."); + xfer_info->cleanup_name =_("Finishing Copy..."); xfer_info->kind = XFER_COPY; /* always show progress during copy */ xfer_info->show_progress_dialog = TRUE; @@ -574,7 +615,9 @@ fs_xfer (const GList *item_uris, g_free (target_dir_uri_text); - gnome_vfs_uri_unref (trash_dir_uri); + if (trash_dir_uri != NULL) { + gnome_vfs_uri_unref (trash_dir_uri); + } gnome_vfs_uri_unref (target_dir_uri); gnome_vfs_uri_unref (source_dir_uri); nautilus_g_list_free_deep (item_names); @@ -681,7 +724,8 @@ fs_move_to_trash (const GList *item_uris, GtkWidget *parent_view) _("OK"), NULL, NULL); bail = TRUE; } else if (gnome_vfs_uri_is_parent (uri, trash_dir_uri, TRUE)) { - item_name = gnome_vfs_uri_extract_short_name (uri); + item_name = nautilus_convert_to_unescaped_string_for_display + (gnome_vfs_uri_extract_short_name (uri)); text = g_strdup_printf ( _("You cannot throw \"%s\" " "into the Trash."), item_name); @@ -716,6 +760,7 @@ fs_move_to_trash (const GList *item_uris, GtkWidget *parent_view) xfer_info->operation_name = _("Moving to Trash"); xfer_info->preparation_name =_("Preparing to Move to Trash..."); + xfer_info->cleanup_name =_("Finishing Move to Trash..."); xfer_info->error_mode = GNOME_VFS_XFER_ERROR_MODE_QUERY; xfer_info->overwrite_mode = GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE; xfer_info->kind = XFER_MOVE_TO_TRASH; @@ -756,6 +801,7 @@ fs_delete (const GList *item_uris, GtkWidget *parent_view) xfer_info->show_progress_dialog = TRUE; xfer_info->operation_name = _("Deleting"); xfer_info->preparation_name =_("Preparing to Delete..."); + xfer_info->cleanup_name =_("Finishing Delete..."); xfer_info->error_mode = GNOME_VFS_XFER_ERROR_MODE_QUERY; xfer_info->overwrite_mode = GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE; xfer_info->kind = XFER_DELETE; @@ -801,6 +847,7 @@ fs_empty_trash (GtkWidget *parent_view) xfer_info->show_progress_dialog = TRUE; xfer_info->operation_name = _("Emptying the Trash"); xfer_info->preparation_name =_("Preparing to Empty the Trash..."); + xfer_info->cleanup_name =_("Finishing Emptying the Trash..."); xfer_info->error_mode = GNOME_VFS_XFER_ERROR_MODE_QUERY; xfer_info->overwrite_mode = GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE; xfer_info->kind = XFER_EMPTY_TRASH; diff --git a/src/file-manager/dfos-xfer.h b/src/file-manager/dfos-xfer.h index 9e9de244d..d9b207d95 100644 --- a/src/file-manager/dfos-xfer.h +++ b/src/file-manager/dfos-xfer.h @@ -52,4 +52,9 @@ void fs_new_folder (GtkWidget *parent_view, gpointer data); void fs_delete (const GList *item_uris, GtkWidget *parent_view); + +/* Prepare an escaped string for display. Unescapes a string in place. + * Frees the original string. + */ +char *nautilus_convert_to_unescaped_string_for_display (char *escaped); #endif /* DFOS_XFER_H */ diff --git a/src/file-manager/fm-directory-view.c b/src/file-manager/fm-directory-view.c index 433d580d0..f3fc89499 100644 --- a/src/file-manager/fm-directory-view.c +++ b/src/file-manager/fm-directory-view.c @@ -1636,10 +1636,14 @@ fm_directory_is_trash (FMDirectoryView *view) result = gnome_vfs_find_directory (directory_uri, GNOME_VFS_DIRECTORY_KIND_TRASH, &trash_dir_uri, TRUE, 0777) == GNOME_VFS_OK; - result &= (gnome_vfs_uri_equal (trash_dir_uri, directory_uri) - || gnome_vfs_uri_is_parent (trash_dir_uri, directory_uri, TRUE)); + if (result) { + result = (gnome_vfs_uri_equal (trash_dir_uri, directory_uri) + || gnome_vfs_uri_is_parent (trash_dir_uri, directory_uri, TRUE)); + } - gnome_vfs_uri_unref (trash_dir_uri); + if (trash_dir_uri) { + gnome_vfs_uri_unref (trash_dir_uri); + } gnome_vfs_uri_unref (directory_uri); g_free (directory); @@ -1667,7 +1671,8 @@ fm_directory_can_move_to_trash (FMDirectoryView *view) /* don't allow trashing items already in the Trash */ result = FALSE; } - gnome_vfs_uri_unref (trash_dir_uri); + if (trash_dir_uri) + gnome_vfs_uri_unref (trash_dir_uri); gnome_vfs_uri_unref (directory_uri); g_free (directory); |