[nautilus] file-conflict-dialog: separate file logic from UI management



commit fd01842f996b7d07baf2aafb0f68308fc5ed2055
Author: Razvan Chitu <razvan ch95 gmail com>
Date:   Sun Aug 21 19:06:51 2016 +0300

    file-conflict-dialog: separate file logic from UI management
    
    In Nautilus, file conflicts are handled by a specific dialog. Previously, the
    dialog class managed both the UI and the related nautilus files. This lead to it
    being inflexible due to operation specific logic being mixed with the rest of
    the functionality. In order to change this, move file logic to a separate module
    and add methods for controlling the UI elements in the dialog.
    
    Create an operation-manager module to handle dialog controlling. Move anything
    related to Nautilus files from the dialog class to the new module.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=770160

 src/Makefile.am                      |    2 +
 src/nautilus-file-conflict-dialog.c  |  473 +++++++++-------------------------
 src/nautilus-file-conflict-dialog.h  |   30 ++-
 src/nautilus-file-operations.c       |  147 ++---------
 src/nautilus-operations-ui-manager.c |  449 ++++++++++++++++++++++++++++++++
 src/nautilus-operations-ui-manager.h |   27 ++
 6 files changed, 648 insertions(+), 480 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 652cab7..6532c01 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -278,6 +278,8 @@ nautilus_no_main_sources = \
        nautilus-rename-file-popover-controller.h \
        nautilus-new-folder-dialog-controller.c \
        nautilus-new-folder-dialog-controller.h \
+       nautilus-operations-ui-manager.c \
+       nautilus-operations-ui-manager.h \
        nautilus-file-operations.c \
        nautilus-file-operations.h \
        nautilus-file-private.h \
diff --git a/src/nautilus-file-conflict-dialog.c b/src/nautilus-file-conflict-dialog.c
index bfce4c9..0ba63a1 100644
--- a/src/nautilus-file-conflict-dialog.c
+++ b/src/nautilus-file-conflict-dialog.c
@@ -32,18 +32,11 @@
 
 #include "nautilus-file.h"
 #include "nautilus-icon-info.h"
+#include "nautilus-operations-ui-manager.h"
 
 struct _NautilusFileConflictDialogDetails
 {
-       /* conflicting objects */
-       NautilusFile *source;
-       NautilusFile *destination;
-       NautilusFile *dest_dir;
-
        gchar *conflict_name;
-       NautilusFileListHandle *handle;
-       gulong src_handler_id;
-       gulong dest_handler_id;
 
        /* UI objects */
        GtkWidget *titles_vbox;
@@ -52,6 +45,7 @@ struct _NautilusFileConflictDialogDetails
        GtkWidget *expander;
        GtkWidget *entry;
        GtkWidget *checkbox;
+        GtkWidget *skip_button;
        GtkWidget *rename_button;
        GtkWidget *replace_button;
        GtkWidget *dest_image;
@@ -66,307 +60,128 @@ G_DEFINE_TYPE (NautilusFileConflictDialog,
        (G_TYPE_INSTANCE_GET_PRIVATE ((object), NAUTILUS_TYPE_FILE_CONFLICT_DIALOG, \
                                      NautilusFileConflictDialogDetails))
 
-static void
-file_icons_changed (NautilusFile *file,
-                   NautilusFileConflictDialog *fcd)
-{
-       GdkPixbuf *pixbuf;
-
-       pixbuf = nautilus_file_get_icon_pixbuf (fcd->details->destination,
-                                               NAUTILUS_CANVAS_ICON_SIZE_SMALL,
-                                               TRUE,
-                                               gtk_widget_get_scale_factor (fcd->details->dest_image),
-                                               NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS);
 
-       gtk_image_set_from_pixbuf (GTK_IMAGE (fcd->details->dest_image), pixbuf);
-       g_object_unref (pixbuf);
-
-       pixbuf = nautilus_file_get_icon_pixbuf (fcd->details->source,
-                                               NAUTILUS_CANVAS_ICON_SIZE_SMALL,
-                                               TRUE,
-                                               gtk_widget_get_scale_factor (fcd->details->src_image),
-                                               NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS);
-
-       gtk_image_set_from_pixbuf (GTK_IMAGE (fcd->details->src_image), pixbuf);
-       g_object_unref (pixbuf);
+void
+nautilus_file_conflict_dialog_set_text (NautilusFileConflictDialog *fcd,
+                                        gchar *primary_text,
+                                        gchar *secondary_text)
+{
+        NautilusFileConflictDialogDetails *details = fcd->details;
+        GtkWidget *label;
+        PangoAttrList *attr_list;
+
+        label = gtk_label_new (primary_text);
+        gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+        gtk_label_set_line_wrap_mode (GTK_LABEL (label), PANGO_WRAP_WORD_CHAR);
+        gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+        gtk_box_pack_start (GTK_BOX (details->titles_vbox),
+                            label, FALSE, FALSE, 0);
+        gtk_widget_show (label);
+
+        attr_list = pango_attr_list_new ();
+        pango_attr_list_insert (attr_list, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
+        pango_attr_list_insert (attr_list, pango_attr_scale_new (PANGO_SCALE_LARGE));
+        g_object_set (label,
+                      "attributes", attr_list,
+                      NULL);
+
+        pango_attr_list_unref (attr_list);
+
+        label = gtk_label_new (secondary_text);
+        gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+        gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+        gtk_box_pack_start (GTK_BOX (details->titles_vbox),
+                            label, FALSE, FALSE, 0);
+        gtk_widget_show (label);
 }
 
-static void
-file_list_ready_cb (GList *files,
-                   gpointer user_data)
+void
+nautilus_file_conflict_dialog_set_images (NautilusFileConflictDialog *fcd,
+                                          GdkPixbuf *destination_pixbuf,
+                                          GdkPixbuf *source_pixbuf)
 {
-       NautilusFileConflictDialog *fcd = user_data;
-       NautilusFile *src, *dest, *dest_dir;
-       time_t src_mtime, dest_mtime;
-       gboolean source_is_dir, dest_is_dir, should_show_type;
-       NautilusFileConflictDialogDetails *details;
-       char *primary_text, *message, *secondary_text;
-       const gchar *message_extra;
-       char *dest_name, *dest_dir_name, *edit_name;
-       char *label_text;
-       char *size, *date, *type = NULL;
-       GdkPixbuf *pixbuf;
-       GtkWidget *label;
-       GString *str;
-       PangoAttrList *attr_list;
-
-       details = fcd->details;
-
-       details->handle = NULL;
-
-       dest_dir = g_list_nth_data (files, 0);
-       dest = g_list_nth_data (files, 1);
-       src = g_list_nth_data (files, 2);
-
-       src_mtime = nautilus_file_get_mtime (src);
-       dest_mtime = nautilus_file_get_mtime (dest);
-
-       dest_name = nautilus_file_get_display_name (dest);
-       dest_dir_name = nautilus_file_get_display_name (dest_dir);
-
-       source_is_dir = nautilus_file_is_directory (src);
-       dest_is_dir = nautilus_file_is_directory (dest);
-
-       type = nautilus_file_get_mime_type (dest);
-       should_show_type = !nautilus_file_is_mime_type (src, type);
-
-       g_free (type);
-       type = NULL;
-
-       /* Set up the right labels */
-       if (dest_is_dir) {
-               if (source_is_dir) {
-                       primary_text = g_strdup_printf
-                               (_("Merge folder “%s”?"),
-                                dest_name);
-
-                       message_extra = 
-                               _("Merging will ask for confirmation before replacing any files in "
-                                 "the folder that conflict with the files being copied.");
-
-                       if (src_mtime > dest_mtime) {
-                               message = g_strdup_printf (
-                                       _("An older folder with the same name already exists in “%s”."),
-                                       dest_dir_name);
-                       } else if (src_mtime < dest_mtime) {
-                               message = g_strdup_printf (
-                                       _("A newer folder with the same name already exists in “%s”."),
-                                       dest_dir_name);
-                       } else {
-                               message = g_strdup_printf (
-                                       _("Another folder with the same name already exists in “%s”."),
-                                       dest_dir_name);
-                       }
-               } else {
-                       message_extra =
-                               _("Replacing it will remove all files in the folder.");
-                       primary_text = g_strdup_printf
-                               (_("Replace folder “%s”?"), dest_name);
-                       message = g_strdup_printf
-                               (_("A folder with the same name already exists in “%s”."),
-                                dest_dir_name);
-               }
-       } else {
-               primary_text = g_strdup_printf
-                       (_("Replace file “%s”?"), dest_name);
-
-               message_extra = _("Replacing it will overwrite its content.");
-
-               if (src_mtime > dest_mtime) {
-                       message = g_strdup_printf (
-                               _("An older file with the same name already exists in “%s”."),
-                               dest_dir_name);
-               } else if (src_mtime < dest_mtime) {
-                       message = g_strdup_printf (
-                               _("A newer file with the same name already exists in “%s”."),
-                               dest_dir_name);
-               } else {
-                       message = g_strdup_printf (
-                               _("Another file with the same name already exists in “%s”."),
-                               dest_dir_name);
-               }
-       }
-
-       secondary_text = g_strdup_printf ("%s\n%s", message, message_extra);
-       g_free (message);
-
-       label = gtk_label_new (primary_text);
-       gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
-       gtk_label_set_line_wrap_mode (GTK_LABEL (label), PANGO_WRAP_WORD_CHAR);
-       gtk_label_set_xalign (GTK_LABEL (label), 0.0);
-       gtk_box_pack_start (GTK_BOX (details->titles_vbox),
-                           label, FALSE, FALSE, 0);
-       gtk_widget_show (label);
-
-       attr_list = pango_attr_list_new ();
-       pango_attr_list_insert (attr_list, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
-       pango_attr_list_insert (attr_list, pango_attr_scale_new (PANGO_SCALE_LARGE));
-       g_object_set (label,
-                     "attributes", attr_list,
-                     NULL);
-
-       pango_attr_list_unref (attr_list);
-
-       label = gtk_label_new (secondary_text);
-       gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
-       gtk_label_set_xalign (GTK_LABEL (label), 0.0);
-       gtk_box_pack_start (GTK_BOX (details->titles_vbox),
-                           label, FALSE, FALSE, 0);
-       gtk_widget_show (label);
-       g_free (primary_text);
-       g_free (secondary_text);
-
-       /* Set up file icons */
-       pixbuf = nautilus_file_get_icon_pixbuf (dest,
-                                               NAUTILUS_CANVAS_ICON_SIZE_SMALL,
-                                               TRUE,
-                                               gtk_widget_get_scale_factor (fcd->details->titles_vbox),
-                                               NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS);
-       details->dest_image = gtk_image_new_from_pixbuf (pixbuf);
-       gtk_box_pack_start (GTK_BOX (details->first_hbox),
-                           details->dest_image, FALSE, FALSE, 0);
-       gtk_widget_show (details->dest_image);
-       g_object_unref (pixbuf);
-
-       pixbuf = nautilus_file_get_icon_pixbuf (src,
-                                               NAUTILUS_CANVAS_ICON_SIZE_SMALL,
-                                               TRUE,
-                                               gtk_widget_get_scale_factor (fcd->details->titles_vbox),
-                                               NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS);
-       details->src_image = gtk_image_new_from_pixbuf (pixbuf);
-       gtk_box_pack_start (GTK_BOX (details->second_hbox),
-                           details->src_image, FALSE, FALSE, 0);
-       gtk_widget_show (details->src_image);
-       g_object_unref (pixbuf);
-
-       /* Set up labels */
-       label = gtk_label_new (NULL);
-       date = nautilus_file_get_string_attribute (dest,
-                                                  "date_modified");
-       size = nautilus_file_get_string_attribute (dest, "size");
-
-       if (should_show_type) {
-               type = nautilus_file_get_string_attribute (dest, "type");
-       }
-
-       str = g_string_new (NULL);
-       if (dest_is_dir) {
-               g_string_append_printf (str, "<b>%s</b>\n", _("Original folder"));
-               g_string_append_printf (str, "%s %s\n", _("Items:"), size);
-       }
-       else {
-               g_string_append_printf (str, "<b>%s</b>\n", _("Original file"));
-               g_string_append_printf (str, "%s %s\n", _("Size:"), size);
-       }
-
-       if (should_show_type) {
-               g_string_append_printf (str, "%s %s\n", _("Type:"), type);
-       }
-
-       g_string_append_printf (str, "%s %s", _("Last modified:"), date);
-
-       label_text = str->str;
-       gtk_label_set_markup (GTK_LABEL (label),
-                             label_text);
-       gtk_box_pack_start (GTK_BOX (details->first_hbox),
-                           label, FALSE, FALSE, 0);
-       gtk_widget_show (label);
-
-       g_free (size);
-       g_free (type);
-       g_free (date);
-       g_string_erase (str, 0, -1);
-
-       /* Second label */
-       label = gtk_label_new (NULL);
-       date = nautilus_file_get_string_attribute (src,
-                                                  "date_modified");
-       size = nautilus_file_get_string_attribute (src, "size");
-
-       if (should_show_type) {
-               type = nautilus_file_get_string_attribute (src, "type");
-       }
-
-       if (source_is_dir) {
-               g_string_append_printf (str, "<b>%s</b>\n", dest_is_dir ? _("Merge with") : _("Replace 
with"));
-               g_string_append_printf (str, "%s %s\n", _("Items:"), size);
-       }
-       else {
-               g_string_append_printf (str, "<b>%s</b>\n", _("Replace with"));
-               g_string_append_printf (str, "%s %s\n", _("Size:"), size);
-       }
-
-       if (should_show_type) {
-               g_string_append_printf (str, "%s %s\n", _("Type:"), type);
-       }
-
-       g_string_append_printf (str, "%s %s", _("Last modified:"), date);
-       label_text = g_string_free (str, FALSE);
-
-       gtk_label_set_markup (GTK_LABEL (label),
-                             label_text);
-       gtk_box_pack_start (GTK_BOX (details->second_hbox),
-                           label, FALSE, FALSE, 0);
-       gtk_widget_show (label);
+        NautilusFileConflictDialogDetails *details = fcd->details;
+
+        if (details->dest_image == NULL) {
+                details->dest_image = gtk_image_new_from_pixbuf (destination_pixbuf);
+                gtk_box_pack_start (GTK_BOX (details->first_hbox),
+                                    details->dest_image, FALSE, FALSE, 0);
+                gtk_widget_show (details->dest_image);
+        } else {
+                gtk_image_set_from_pixbuf (GTK_IMAGE (details->dest_image),
+                                           destination_pixbuf);
+        }
+
+        if (details->src_image == NULL) {
+                details->src_image = gtk_image_new_from_pixbuf (source_pixbuf);
+                gtk_box_pack_start (GTK_BOX (details->second_hbox),
+                                    details->src_image, FALSE, FALSE, 0);
+                gtk_widget_show (details->src_image);
+        } else {
+                gtk_image_set_from_pixbuf (GTK_IMAGE (details->src_image),
+                                           source_pixbuf);
+        }
+}
 
-       g_free (size);
-       g_free (date);
-       g_free (type);
-       g_free (label_text);
+void
+nautilus_file_conflict_dialog_set_file_labels (NautilusFileConflictDialog *fcd,
+                                               gchar *destination_label,
+                                               gchar *source_label)
+{
+        NautilusFileConflictDialogDetails *details = fcd->details;
+        GtkWidget *label;
+
+        label = gtk_label_new (NULL);
+        gtk_label_set_markup (GTK_LABEL (label),
+                              destination_label);
+        gtk_box_pack_start (GTK_BOX (details->first_hbox),
+                            label, FALSE, FALSE, 0);
+        gtk_widget_show (label);
+
+        label = gtk_label_new (NULL);
+        gtk_label_set_markup (GTK_LABEL (label),
+                              source_label);
+        gtk_box_pack_start (GTK_BOX (details->second_hbox),
+                            label, FALSE, FALSE, 0);
+        gtk_widget_show (label);
+}
 
-       /* Populate the entry */
-       edit_name = nautilus_file_get_edit_name (dest);
-       details->conflict_name = edit_name;
+void
+nautilus_file_conflict_dialog_set_conflict_name (NautilusFileConflictDialog *fcd,
+                                                 gchar *conflict_name)
+{
+        NautilusFileConflictDialogDetails *details = fcd->details;
 
-       gtk_entry_set_text (GTK_ENTRY (details->entry), edit_name);
+        details->conflict_name = g_strdup (conflict_name);
 
-       if (source_is_dir && dest_is_dir) {
-               gtk_button_set_label (GTK_BUTTON (details->replace_button),
-                                     _("Merge"));
-       }
+        gtk_entry_set_text (GTK_ENTRY (details->entry), details->conflict_name);
 
-       nautilus_file_monitor_add (src, fcd, NAUTILUS_FILE_ATTRIBUTES_FOR_ICON);
-       nautilus_file_monitor_add (dest, fcd, NAUTILUS_FILE_ATTRIBUTES_FOR_ICON);
-
-       details->src_handler_id = g_signal_connect (src, "changed",
-                         G_CALLBACK (file_icons_changed), fcd);
-       details->dest_handler_id = g_signal_connect (dest, "changed",
-                         G_CALLBACK (file_icons_changed), fcd);
 }
 
-static void
-build_dialog_appearance (NautilusFileConflictDialog *fcd)
+void
+nautilus_file_conflict_dialog_set_replace_button_label (NautilusFileConflictDialog *fcd,
+                                                        gchar *label)
 {
-       GList *files = NULL;
-       NautilusFileConflictDialogDetails *details = fcd->details;
+        NautilusFileConflictDialogDetails *details = fcd->details;
 
-       files = g_list_prepend (files, details->source);
-       files = g_list_prepend (files, details->destination);
-       files = g_list_prepend (files, details->dest_dir);
-
-       nautilus_file_list_call_when_ready (files,
-                                           NAUTILUS_FILE_ATTRIBUTES_FOR_ICON,
-                                           &details->handle, file_list_ready_cb, fcd);
-       g_list_free (files);
+        gtk_button_set_label (GTK_BUTTON (details->replace_button),
+                              label);
 }
 
-static void
-set_source_and_destination (GtkWidget *w,
-                           GFile *source,
-                           GFile *destination,
-                           GFile *dest_dir)
+void
+nautilus_file_conflict_dialog_disable_skip (NautilusFileConflictDialog *fcd)
 {
-       NautilusFileConflictDialog *dialog;
-       NautilusFileConflictDialogDetails *details;
+        NautilusFileConflictDialogDetails *details = fcd->details;
 
-       dialog = NAUTILUS_FILE_CONFLICT_DIALOG (w);
-       details = dialog->details;
+        gtk_widget_hide (details->skip_button);
+}
 
-       details->source = nautilus_file_get (source);
-       details->destination = nautilus_file_get (destination);
-       details->dest_dir = nautilus_file_get (dest_dir);
+void
+nautilus_file_conflict_dialog_disable_apply_to_all (NautilusFileConflictDialog *fcd)
+{
+        NautilusFileConflictDialogDetails *details = fcd->details;
 
-       build_dialog_appearance (dialog);
+        gtk_widget_hide (details->checkbox);
 }
 
 static void
@@ -549,12 +364,15 @@ nautilus_file_conflict_dialog_init (NautilusFileConflictDialog *fcd)
                          G_CALLBACK (checkbox_toggled_cb), dialog);
 
        /* Add buttons */
-       gtk_dialog_add_buttons (dialog,
-                               _("_Cancel"),
-                               GTK_RESPONSE_CANCEL,
-                               _("_Skip"),
-                               CONFLICT_RESPONSE_SKIP,
-                               NULL);
+        gtk_dialog_add_button (dialog,
+                               _("_Cancel"),
+                               GTK_RESPONSE_CANCEL);
+
+        details->skip_button =
+                gtk_dialog_add_button (dialog,
+                                       _("_Skip"),
+                                       CONFLICT_RESPONSE_SKIP);
+
        details->rename_button =
                gtk_dialog_add_button (dialog,
                                       _("Re_name"),
@@ -583,24 +401,6 @@ do_finalize (GObject *self)
 
        g_free (details->conflict_name);
 
-       if (details->handle != NULL) {
-               nautilus_file_list_cancel_call_when_ready (details->handle);
-       }
-
-       if (details->src_handler_id) {
-               g_signal_handler_disconnect (details->source, details->src_handler_id);
-               nautilus_file_monitor_remove (details->source, self);
-       }
-
-       if (details->dest_handler_id) {
-               g_signal_handler_disconnect (details->destination, details->dest_handler_id);
-               nautilus_file_monitor_remove (details->destination, self);
-       }
-
-       nautilus_file_unref (details->source);
-       nautilus_file_unref (details->destination);
-       nautilus_file_unref (details->dest_dir);
-
        G_OBJECT_CLASS (nautilus_file_conflict_dialog_parent_class)->finalize (self);
 }
 
@@ -626,45 +426,18 @@ nautilus_file_conflict_dialog_get_apply_to_all (NautilusFileConflictDialog *dial
                (GTK_TOGGLE_BUTTON (dialog->details->checkbox));
 }
 
-GtkWidget *
-nautilus_file_conflict_dialog_new (GtkWindow *parent,
-                                  GFile *source,
-                                  GFile *destination,
-                                  GFile *dest_dir)
+NautilusFileConflictDialog *
+nautilus_file_conflict_dialog_new (GtkWindow *parent)
 {
-       GtkWidget *dialog;
-       NautilusFile *src, *dest;
-       gboolean source_is_dir, dest_is_dir;
-
-       src = nautilus_file_get (source);
-       dest = nautilus_file_get (destination);
-
-       source_is_dir = nautilus_file_is_directory (src);
-       dest_is_dir = nautilus_file_is_directory (dest);
-
-       if (source_is_dir) {
-               dialog = GTK_WIDGET (g_object_new (NAUTILUS_TYPE_FILE_CONFLICT_DIALOG,
-                                                  "use-header-bar", TRUE,
-                                                  "modal", TRUE,
-                                                  "title", dest_is_dir ? _("Merge Folder") : _("File and 
Folder conflict"),
-                                                  NULL));
-       } else {
-               dialog = GTK_WIDGET (g_object_new (NAUTILUS_TYPE_FILE_CONFLICT_DIALOG,
-                                                  "use-header-bar", TRUE,
-                                                  "modal", TRUE,
-                                                  "title", dest_is_dir ? _("File and Folder conflict") : 
_("File conflict"),
-                                                  NULL));
-       }
-       
-       set_source_and_destination (dialog,
-                                   source,
-                                   destination,
-                                   dest_dir);
+        NautilusFileConflictDialog *dialog;
+
+        dialog = NAUTILUS_FILE_CONFLICT_DIALOG (g_object_new (NAUTILUS_TYPE_FILE_CONFLICT_DIALOG,
+                                                "use-header-bar", TRUE,
+                                                "modal", TRUE,
+                                                NULL));
+
        gtk_window_set_transient_for (GTK_WINDOW (dialog),
                                      parent);
 
-        g_object_unref (src);
-        g_object_unref (dest);
-
        return dialog;
 }
diff --git a/src/nautilus-file-conflict-dialog.h b/src/nautilus-file-conflict-dialog.h
index b7767ce..eee92d3 100644
--- a/src/nautilus-file-conflict-dialog.h
+++ b/src/nautilus-file-conflict-dialog.h
@@ -56,19 +56,27 @@ struct _NautilusFileConflictDialogClass {
        GtkDialogClass parent_class;
 };
 
-enum
-{
-       CONFLICT_RESPONSE_SKIP = 1,
-       CONFLICT_RESPONSE_REPLACE = 2,
-       CONFLICT_RESPONSE_RENAME = 3,
-};
-
 GType nautilus_file_conflict_dialog_get_type (void) G_GNUC_CONST;
 
-GtkWidget* nautilus_file_conflict_dialog_new              (GtkWindow *parent,
-                                                          GFile *source,
-                                                          GFile *destination,
-                                                          GFile *dest_dir);
+NautilusFileConflictDialog* nautilus_file_conflict_dialog_new (GtkWindow *parent);
+
+void nautilus_file_conflict_dialog_set_text (NautilusFileConflictDialog *fcd,
+                                             gchar *primary_text,
+                                             gchar *secondary_text);
+void nautilus_file_conflict_dialog_set_images (NautilusFileConflictDialog *fcd,
+                                               GdkPixbuf *source_pixbuf,
+                                               GdkPixbuf *destination_pixbuf);
+void nautilus_file_conflict_dialog_set_file_labels (NautilusFileConflictDialog *fcd,
+                                                    gchar *destination_label,
+                                                    gchar *source_label);
+void nautilus_file_conflict_dialog_set_conflict_name (NautilusFileConflictDialog *fcd,
+                                                      gchar *conflict_name);
+void nautilus_file_conflict_dialog_set_replace_button_label (NautilusFileConflictDialog *fcd,
+                                                             gchar *label);
+
+void nautilus_file_conflict_dialog_disable_skip (NautilusFileConflictDialog *fcd);
+void nautilus_file_conflict_dialog_disable_apply_to_all (NautilusFileConflictDialog *fcd);
+
 char*      nautilus_file_conflict_dialog_get_new_name     (NautilusFileConflictDialog *dialog);
 gboolean   nautilus_file_conflict_dialog_get_apply_to_all (NautilusFileConflictDialog *dialog);
 
diff --git a/src/nautilus-file-operations.c b/src/nautilus-file-operations.c
index 804a1c7..5184205 100644
--- a/src/nautilus-file-operations.c
+++ b/src/nautilus-file-operations.c
@@ -51,13 +51,13 @@
 #include <gtk/gtk.h>
 #include <gio/gio.h>
 #include <glib.h>
+#include "nautilus-operations-ui-manager.h"
 #include "nautilus-file-changes-queue.h"
 #include "nautilus-file-private.h"
 #include "nautilus-global-preferences.h"
 #include "nautilus-link.h"
 #include "nautilus-trash-monitor.h"
 #include "nautilus-file-utilities.h"
-#include "nautilus-file-conflict-dialog.h"
 #include "nautilus-file-undo-operations.h"
 #include "nautilus-file-undo-manager.h"
 
@@ -4292,117 +4292,26 @@ is_trusted_desktop_file (GFile *file,
        return res;
 }
 
-typedef struct {
-       int id;
-       char *new_name;
-       gboolean apply_to_all;
-} ConflictResponseData;
-
-typedef struct {
-       GFile *src;
-       GFile *dest;
-       GFile *dest_dir;
-       GtkWindow *parent;
-       ConflictResponseData *resp_data;
-       /* Dialogs are ran from operation threads, which need to be blocked until
-        * the user gives a valid response
-        */
-       gboolean completed;
-       GMutex mutex;
-       GCond cond;
-} ConflictDialogData;
-
-static gboolean
-do_run_conflict_dialog (gpointer _data)
-{
-       ConflictDialogData *data = _data;
-       GtkWidget *dialog;
-       int response;
-
-       g_mutex_lock (&data->mutex);
-
-       dialog = nautilus_file_conflict_dialog_new (data->parent,
-                                                   data->src,
-                                                   data->dest,
-                                                   data->dest_dir);
-       response = gtk_dialog_run (GTK_DIALOG (dialog));
-
-       if (response == CONFLICT_RESPONSE_RENAME) {
-               data->resp_data->new_name = 
-                       nautilus_file_conflict_dialog_get_new_name (NAUTILUS_FILE_CONFLICT_DIALOG (dialog));
-       } else if (response != GTK_RESPONSE_CANCEL &&
-                  response != GTK_RESPONSE_NONE) {
-                  data->resp_data->apply_to_all =
-                          nautilus_file_conflict_dialog_get_apply_to_all 
-                               (NAUTILUS_FILE_CONFLICT_DIALOG (dialog));
-       }
-
-       data->resp_data->id = response;
-       data->completed = TRUE;
-
-       gtk_widget_destroy (dialog);
-
-       g_cond_signal (&data->cond);
-       g_mutex_unlock (&data->mutex);
-
-       return FALSE;
-}
-
-static ConflictResponseData *
-run_conflict_dialog (CommonJob *job,
-                    GFile *src,
-                    GFile *dest,
-                    GFile *dest_dir)
+static FileConflictResponse *
+handle_copy_move_conflict (CommonJob *job,
+                           GFile     *src,
+                           GFile     *dest,
+                           GFile     *dest_dir)
 {
-       ConflictDialogData *data;
-       ConflictResponseData *resp_data;
-
-       g_timer_stop (job->time);
-
-       data = g_slice_new0 (ConflictDialogData);
-       data->parent = job->parent_window;
-       data->src = src;
-       data->dest = dest;
-       data->dest_dir = dest_dir;
-
-       resp_data = g_slice_new0 (ConflictResponseData);
-       resp_data->new_name = NULL;
-       data->resp_data = resp_data;
-
-       data->completed = FALSE;
-       g_mutex_init (&data->mutex);
-       g_cond_init (&data->cond);
+        FileConflictResponse *response;
 
-       nautilus_progress_info_pause (job->progress);
+        g_timer_stop (job->time);
+        nautilus_progress_info_pause (job->progress);
 
-       g_mutex_lock (&data->mutex);
+        response = copy_move_conflict_ask_user_action (job->parent_window,
+                                                       src,
+                                                       dest,
+                                                       dest_dir);
 
-       g_main_context_invoke (NULL,
-                              do_run_conflict_dialog,
-                              data);
+        nautilus_progress_info_resume (job->progress);
+        g_timer_continue (job->time);
 
-       while (!data->completed) {
-               g_cond_wait (&data->cond, &data->mutex);
-       }
-
-       nautilus_progress_info_resume (job->progress);
-
-       g_mutex_unlock (&data->mutex);
-       g_mutex_clear (&data->mutex);
-       g_cond_clear (&data->cond);
-
-       g_slice_free (ConflictDialogData, data);
-
-       g_timer_continue (job->time);
-
-       return resp_data;
-}
-
-static void
-conflict_response_data_free (ConflictResponseData *data)
-{
-       g_free (data->new_name);
-       g_slice_free (ConflictResponseData, data);
+        return response;
 }
 
 static GFile *
@@ -4649,7 +4558,7 @@ copy_move_file (CopyMoveJob *copy_job,
        if (!overwrite &&
            IS_IO_ERROR (error, EXISTS)) {
                gboolean is_merge;
-               ConflictResponseData *response;
+               FileConflictResponse *response;
 
                g_error_free (error);
 
@@ -4675,17 +4584,17 @@ copy_move_file (CopyMoveJob *copy_job,
                        goto out;
                }
 
-               response = run_conflict_dialog (job, src, dest, dest_dir);      
+               response = handle_copy_move_conflict (job, src, dest, dest_dir);
 
                if (response->id == GTK_RESPONSE_CANCEL ||
                    response->id == GTK_RESPONSE_DELETE_EVENT) {
-                       conflict_response_data_free (response);
+                       file_conflict_response_free (response);
                        abort_job (job);
                } else if (response->id == CONFLICT_RESPONSE_SKIP) {
                        if (response->apply_to_all) {
                                job->skip_all_conflict = TRUE;
                        }
-                       conflict_response_data_free (response);
+                       file_conflict_response_free (response);
                } else if (response->id == CONFLICT_RESPONSE_REPLACE) { /* merge/replace */
                        if (response->apply_to_all) {
                                if (is_merge) {
@@ -4695,13 +4604,13 @@ copy_move_file (CopyMoveJob *copy_job,
                                }
                        }
                        overwrite = TRUE;
-                       conflict_response_data_free (response);
+                       file_conflict_response_free (response);
                        goto retry;
                } else if (response->id == CONFLICT_RESPONSE_RENAME) {
                        g_object_unref (dest);
                        dest = get_target_file_for_display_name (dest_dir,
                                                                 response->new_name);
-                       conflict_response_data_free (response);
+                       file_conflict_response_free (response);
                        goto retry;
                } else {
                        g_assert_not_reached ();
@@ -5292,7 +5201,7 @@ move_file_prepare (CopyMoveJob *move_job,
        else if (!overwrite &&
                 IS_IO_ERROR (error, EXISTS)) {
                gboolean is_merge;
-               ConflictResponseData *response;
+               FileConflictResponse *response;
                
                g_error_free (error);
 
@@ -5311,17 +5220,17 @@ move_file_prepare (CopyMoveJob *move_job,
                        goto out;
                }
 
-               response = run_conflict_dialog (job, src, dest, dest_dir);
+               response = handle_copy_move_conflict (job, src, dest, dest_dir);
 
                if (response->id == GTK_RESPONSE_CANCEL ||
                    response->id == GTK_RESPONSE_DELETE_EVENT) {
-                       conflict_response_data_free (response); 
+                       file_conflict_response_free (response);
                        abort_job (job);
                } else if (response->id == CONFLICT_RESPONSE_SKIP) {
                        if (response->apply_to_all) {
                                job->skip_all_conflict = TRUE;
                        }
-                       conflict_response_data_free (response);
+                       file_conflict_response_free (response);
                } else if (response->id == CONFLICT_RESPONSE_REPLACE) { /* merge/replace */
                        if (response->apply_to_all) {
                                if (is_merge) {
@@ -5331,13 +5240,13 @@ move_file_prepare (CopyMoveJob *move_job,
                                }
                        }
                        overwrite = TRUE;
-                       conflict_response_data_free (response);
+                       file_conflict_response_free (response);
                        goto retry;
                } else if (response->id == CONFLICT_RESPONSE_RENAME) {
                        g_object_unref (dest);
                        dest = get_target_file_for_display_name (dest_dir,
                                                                 response->new_name);
-                       conflict_response_data_free (response);
+                       file_conflict_response_free (response);
                        goto retry;
                } else {
                        g_assert_not_reached ();
diff --git a/src/nautilus-operations-ui-manager.c b/src/nautilus-operations-ui-manager.c
new file mode 100644
index 0000000..022c8cc
--- /dev/null
+++ b/src/nautilus-operations-ui-manager.c
@@ -0,0 +1,449 @@
+#include <glib/gi18n.h>
+
+#include "nautilus-operations-ui-manager.h"
+
+#include "nautilus-file.h"
+#include "nautilus-file-operations.h"
+#include "nautilus-file-conflict-dialog.h"
+
+typedef struct {
+        GSourceFunc source_func;
+        gpointer user_data;
+        GMutex mutex;
+        GCond cond;
+        gboolean completed;
+} ContextInvokeData;
+
+G_LOCK_DEFINE_STATIC (main_context_sync);
+
+static gboolean
+invoke_main_context_source_func_wrapper (gpointer user_data)
+{
+        ContextInvokeData *data = user_data;
+
+        g_mutex_lock (&data->mutex);
+
+        while (data->source_func (data->user_data));
+
+        data->completed = TRUE;
+
+        g_cond_signal (&data->cond);
+        g_mutex_unlock (&data->mutex);
+
+        return G_SOURCE_REMOVE;
+}
+
+/* This function is used to run UI on the main thread in order to ask the user
+ * for an action during an operation. Since the operation cannot progress until
+ * an action is provided by the user, the current thread needs to be blocked.
+ * For this we wait on a condition on the shared data. We proceed further
+ * unblocking the thread when the condition is set in the UI thread.
+ */
+static void
+invoke_main_context_sync (GMainContext *main_context,
+                          GSourceFunc   source_func,
+                          gpointer      user_data)
+{
+        ContextInvokeData data;
+        /* Allow only one thread at a time to invoke the main context so we
+         * don't get race conditions which could lead to multiple dialogs being
+         * displayed at the same time
+         */
+        G_LOCK (main_context_sync);
+
+        data.source_func = source_func;
+        data.user_data = user_data;
+
+        g_mutex_init (&data.mutex);
+        g_cond_init (&data.cond);
+        data.completed = FALSE;
+
+        g_mutex_lock (&data.mutex);
+
+        g_main_context_invoke (main_context,
+                               invoke_main_context_source_func_wrapper,
+                               &data);
+
+        while (!data.completed) {
+                g_cond_wait (&data.cond, &data.mutex);
+        }
+
+        g_mutex_unlock (&data.mutex);
+
+        G_UNLOCK (main_context_sync);
+
+        g_mutex_clear (&data.mutex);
+        g_cond_clear (&data.cond);
+}
+
+typedef struct {
+        GFile *source_name;
+        GFile *destination_name;
+        GFile *destination_directory_name;
+
+        GtkWindow *parent;
+
+        FileConflictResponse *response;
+
+        NautilusFile *source;
+        NautilusFile *destination;
+        NautilusFile *destination_directory;
+
+        NautilusFileConflictDialog *dialog;
+
+        NautilusFileListCallback on_file_list_ready;
+        NautilusFileListHandle *handle;
+        gulong source_handler_id;
+        gulong destination_handler_id;
+} FileConflictDialogData;
+
+void
+file_conflict_response_free (FileConflictResponse *response)
+{
+        g_free (response->new_name);
+        g_slice_free (FileConflictResponse, response);
+}
+
+static void
+set_copy_move_dialog_text (FileConflictDialogData *data)
+{
+        g_autofree gchar *primary_text = NULL;
+        g_autofree gchar *secondary_text = NULL;
+        const gchar *message_extra;
+        time_t source_mtime;
+        time_t destination_mtime;
+        g_autofree gchar *message = NULL;
+        g_autofree gchar *destination_name;
+        g_autofree gchar *destination_directory_name;
+        gboolean source_is_directory;
+        gboolean destination_is_directory;
+
+        source_mtime = nautilus_file_get_mtime (data->source);
+        destination_mtime = nautilus_file_get_mtime (data->destination);
+
+        destination_name = nautilus_file_get_display_name (data->destination);
+        destination_directory_name = nautilus_file_get_display_name (data->destination_directory);
+
+        source_is_directory = nautilus_file_is_directory (data->source);
+        destination_is_directory = nautilus_file_is_directory (data->destination);
+
+        if (destination_is_directory) {
+                if (source_is_directory) {
+                        primary_text = g_strdup_printf (_("Merge folder “%s”?"),
+                                                        destination_name);
+
+                        message_extra = _("Merging will ask for confirmation before replacing any files in "
+                                          "the folder that conflict with the files being copied.");
+
+                        if (source_mtime > destination_mtime) {
+                                message = g_strdup_printf (_("An older folder with the same name already 
exists in “%s”."),
+                                                           destination_directory_name);
+                        } else if (source_mtime < destination_mtime) {
+                                message = g_strdup_printf (_("A newer folder with the same name already 
exists in “%s”."),
+                                                           destination_directory_name);
+                        } else {
+                                message = g_strdup_printf (_("Another folder with the same name already 
exists in “%s”."),
+                                                           destination_directory_name);
+                        }
+                } else {
+                        primary_text = g_strdup_printf (_("Replace folder “%s”?"),
+                                                        destination_name);
+                        message_extra = _("Replacing it will remove all files in the folder.");
+                        message = g_strdup_printf (_("A folder with the same name already exists in “%s”."),
+                                                   destination_directory_name);
+                }
+        } else {
+                primary_text = g_strdup_printf (_("Replace file “%s”?"),
+                                                destination_name);
+
+                message_extra = _("Replacing it will overwrite its content.");
+
+                if (source_mtime > destination_mtime) {
+                        message = g_strdup_printf (_("An older file with the same name already exists in 
“%s”."),
+                                                   destination_directory_name);
+                } else if (source_mtime < destination_mtime) {
+                        message = g_strdup_printf (_("A newer file with the same name already exists in 
“%s”."),
+                                                   destination_directory_name);
+                } else {
+                        message = g_strdup_printf (_("Another file with the same name already exists in 
“%s”."),
+                                                   destination_directory_name);
+                }
+        }
+
+        secondary_text = g_strdup_printf ("%s\n%s", message, message_extra);
+
+        nautilus_file_conflict_dialog_set_text (data->dialog,
+                                                primary_text,
+                                                secondary_text);
+}
+
+static void
+set_images (FileConflictDialogData *data)
+{
+        GdkPixbuf *source_pixbuf;
+        GdkPixbuf *destination_pixbuf;
+
+        destination_pixbuf = nautilus_file_get_icon_pixbuf (data->destination,
+                                                            NAUTILUS_CANVAS_ICON_SIZE_SMALL,
+                                                            TRUE,
+                                                            1,
+                                                            NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS);
+
+        source_pixbuf = nautilus_file_get_icon_pixbuf (data->source,
+                                                       NAUTILUS_CANVAS_ICON_SIZE_SMALL,
+                                                       TRUE,
+                                                       1,
+                                                       NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS);
+
+        nautilus_file_conflict_dialog_set_images (data->dialog,
+                                                  destination_pixbuf,
+                                                  source_pixbuf);
+
+        g_object_unref (destination_pixbuf);
+        g_object_unref (source_pixbuf);
+}
+
+static void
+set_file_labels (FileConflictDialogData *data)
+{
+        GString *destination_label;
+        GString *source_label;
+        gboolean source_is_directory;
+        gboolean destination_is_directory;
+        gboolean should_show_type;
+        g_autofree char *destination_mime_type = NULL;
+        g_autofree char *destination_date = NULL;
+        g_autofree char *destination_size = NULL;
+        g_autofree char *destination_type = NULL;
+        g_autofree char *source_date = NULL;
+        g_autofree char *source_size = NULL;
+        g_autofree char *source_type = NULL;
+
+        source_is_directory = nautilus_file_is_directory (data->source);
+        destination_is_directory = nautilus_file_is_directory (data->destination);
+
+        destination_mime_type = nautilus_file_get_mime_type (data->destination);
+        should_show_type = !nautilus_file_is_mime_type (data->source,
+                                                        destination_mime_type);
+
+        destination_date = nautilus_file_get_string_attribute (data->destination,
+                                                               "date_modified");
+        destination_size = nautilus_file_get_string_attribute (data->destination,
+                                                               "size");
+
+        if (should_show_type) {
+                destination_type = nautilus_file_get_string_attribute (data->destination,
+                                                                       "type");
+        }
+
+        destination_label = g_string_new (NULL);
+        if (destination_is_directory) {
+                g_string_append_printf (destination_label, "<b>%s</b>\n", _("Original folder"));
+                g_string_append_printf (destination_label, "%s %s\n", _("Items:"), destination_size);
+        }
+        else {
+                g_string_append_printf (destination_label, "<b>%s</b>\n", _("Original file"));
+                g_string_append_printf (destination_label, "%s %s\n", _("Size:"), destination_size);
+        }
+
+        if (should_show_type) {
+                g_string_append_printf (destination_label, "%s %s\n", _("Type:"), destination_type);
+        }
+
+        g_string_append_printf (destination_label, "%s %s", _("Last modified:"), destination_date);
+
+        source_date = nautilus_file_get_string_attribute (data->source,
+                                                          "date_modified");
+        source_size = nautilus_file_get_string_attribute (data->source,
+                                                          "size");
+
+        if (should_show_type) {
+                source_type = nautilus_file_get_string_attribute (data->source,
+                                                                  "type");
+        }
+
+        source_label = g_string_new (NULL);
+        if (source_is_directory) {
+                g_string_append_printf (source_label, "<b>%s</b>\n",
+                                        destination_is_directory ?
+                                        _("Merge with") : _("Replace with"));
+                g_string_append_printf (source_label, "%s %s\n", _("Items:"), source_size);
+        }
+        else {
+                g_string_append_printf (source_label, "<b>%s</b>\n", _("Replace with"));
+                g_string_append_printf (source_label, "%s %s\n", _("Size:"), source_size);
+        }
+
+        if (should_show_type) {
+                g_string_append_printf (source_label, "%s %s\n", _("Type:"), source_type);
+        }
+
+        g_string_append_printf (source_label, "%s %s", _("Last modified:"), source_date);
+
+        nautilus_file_conflict_dialog_set_file_labels (data->dialog,
+                                                       destination_label->str,
+                                                       source_label->str);
+
+        g_string_free (destination_label, TRUE);
+        g_string_free (source_label, TRUE);
+}
+
+static void
+set_conflict_name (FileConflictDialogData *data)
+{
+        g_autofree gchar *edit_name;
+
+        edit_name = nautilus_file_get_edit_name (data->destination);
+
+        nautilus_file_conflict_dialog_set_conflict_name (data->dialog,
+                                                         edit_name);
+}
+
+static void
+set_replace_button_label (FileConflictDialogData *data)
+{
+        gboolean source_is_directory, destination_is_directory;
+
+        source_is_directory = nautilus_file_is_directory (data->source);
+        destination_is_directory = nautilus_file_is_directory (data->destination);
+
+        if (source_is_directory && destination_is_directory) {
+                nautilus_file_conflict_dialog_set_replace_button_label (data->dialog,
+                                                                        _("Merge"));
+        }
+}
+
+static void
+file_icons_changed (NautilusFile           *file,
+                    FileConflictDialogData *data)
+{
+        set_images (data);
+}
+
+static void
+copy_move_conflict_on_file_list_ready (GList    *files,
+                                       gpointer  user_data)
+{
+        FileConflictDialogData *data = user_data;
+        g_autofree gchar *title;
+
+        data->handle = NULL;
+
+        if (nautilus_file_is_directory (data->source)) {
+                title = g_strdup (nautilus_file_is_directory (data->destination) ?
+                                  _("Merge Folder") :
+                                  _("File and Folder conflict"));
+        } else {
+                title = g_strdup (nautilus_file_is_directory (data->destination) ?
+                                  _("File and Folder conflict") :
+                                  _("File conflict"));
+        }
+
+        gtk_window_set_title (GTK_WINDOW (data->dialog), title);
+
+        set_copy_move_dialog_text (data);
+
+        set_images (data);
+
+        set_file_labels (data);
+
+        set_conflict_name (data);
+
+        set_replace_button_label (data);
+
+        nautilus_file_monitor_add (data->source, data, NAUTILUS_FILE_ATTRIBUTES_FOR_ICON);
+        nautilus_file_monitor_add (data->destination, data, NAUTILUS_FILE_ATTRIBUTES_FOR_ICON);
+
+        data->source_handler_id = g_signal_connect (data->source, "changed",
+                                                    G_CALLBACK (file_icons_changed), data);
+        data->destination_handler_id = g_signal_connect (data->destination, "changed",
+                                                         G_CALLBACK (file_icons_changed), data);
+}
+
+static gboolean
+run_file_conflict_dialog (gpointer user_data)
+{
+        FileConflictDialogData *data = user_data;
+        int response_id;
+        GList *files = NULL;
+
+        data->source = nautilus_file_get (data->source_name);
+        data->destination = nautilus_file_get (data->destination_name);
+        data->destination_directory = nautilus_file_get (data->destination_directory_name);
+
+        data->dialog = nautilus_file_conflict_dialog_new (data->parent);
+
+        files = g_list_prepend (files, data->source);
+        files = g_list_prepend (files, data->destination);
+        files = g_list_prepend (files, data->destination_directory);
+
+        nautilus_file_list_call_when_ready (files,
+                                            NAUTILUS_FILE_ATTRIBUTES_FOR_ICON,
+                                            &data->handle,
+                                            data->on_file_list_ready,
+                                            data);
+
+        response_id = gtk_dialog_run (GTK_DIALOG (data->dialog));
+
+        if (data->handle != NULL) {
+                nautilus_file_list_cancel_call_when_ready (data->handle);
+        }
+
+        if (data->source_handler_id) {
+                g_signal_handler_disconnect (data->source, data->source_handler_id);
+                nautilus_file_monitor_remove (data->source, data);
+        }
+
+        if (data->destination_handler_id) {
+                g_signal_handler_disconnect (data->destination, data->destination_handler_id);
+                nautilus_file_monitor_remove (data->destination, data);
+        }
+
+        if (response_id == CONFLICT_RESPONSE_RENAME) {
+                data->response->new_name =
+                        nautilus_file_conflict_dialog_get_new_name (data->dialog);
+        } else if (response_id != GTK_RESPONSE_CANCEL ||
+                   response_id != GTK_RESPONSE_NONE) {
+                   data->response->apply_to_all =
+                           nautilus_file_conflict_dialog_get_apply_to_all (data->dialog);
+        }
+
+        data->response->id = response_id;
+
+        gtk_widget_destroy (GTK_WIDGET (data->dialog));
+
+        nautilus_file_unref (data->source);
+        nautilus_file_unref (data->destination);
+        nautilus_file_unref (data->destination_directory);
+        g_list_free (files);
+
+        return G_SOURCE_REMOVE;
+}
+
+FileConflictResponse *
+copy_move_conflict_ask_user_action (GtkWindow *parent_window,
+                                    GFile     *source_name,
+                                    GFile     *destination_name,
+                                    GFile     *destination_directory_name)
+{
+        FileConflictDialogData *data;
+
+        data = g_slice_new0 (FileConflictDialogData);
+        data->parent = parent_window;
+        data->source_name = source_name;
+        data->destination_name = destination_name;
+        data->destination_directory_name = destination_directory_name;
+
+        data->response = g_slice_new0 (FileConflictResponse);
+        data->response->new_name = NULL;
+
+        data->on_file_list_ready = copy_move_conflict_on_file_list_ready;
+
+        invoke_main_context_sync (NULL,
+                                  run_file_conflict_dialog,
+                                  data);
+
+        g_slice_free (FileConflictDialogData, data);
+
+        return data->response;
+}
diff --git a/src/nautilus-operations-ui-manager.h b/src/nautilus-operations-ui-manager.h
new file mode 100644
index 0000000..8c9102c
--- /dev/null
+++ b/src/nautilus-operations-ui-manager.h
@@ -0,0 +1,27 @@
+#ifndef NAUTILUS_OPERATIONS_UI_MANAGER
+#define NAUTILUS_OPERATIONS_UI_MANAGER
+
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+
+typedef struct {
+    int id;
+    char *new_name;
+    gboolean apply_to_all;
+} FileConflictResponse;
+
+void file_conflict_response_free (FileConflictResponse *data);
+
+FileConflictResponse * copy_move_conflict_ask_user_action (GtkWindow *parent_window,
+                                                           GFile     *src,
+                                                           GFile     *dest,
+                                                           GFile     *dest_dir);
+
+enum
+{
+    CONFLICT_RESPONSE_SKIP = 1,
+    CONFLICT_RESPONSE_REPLACE = 2,
+    CONFLICT_RESPONSE_RENAME = 3,
+};
+
+#endif /* NAUTILUS_OPERATIONS_UI_MANAGER */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]