[nautilus/wip/razvan/automatic-decompression: 5/7] file-conflict-dialog: separate file logic from UI management



commit ec2dd2d00a2aa2978ea810ae5e31c872e59df8d8
Author: Razvan Chitu <razvan ch95 gmail com>
Date:   Fri Jun 24 00:13:54 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.
     # Please enter the commit message for your changes.

 src/Makefile.am                     |    2 +
 src/nautilus-file-conflict-dialog.c |  472 +++++++++--------------------------
 src/nautilus-file-conflict-dialog.h |   23 ++-
 src/nautilus-file-operations.c      |  119 ++--------
 src/nautilus-operations-manager.c   |  420 +++++++++++++++++++++++++++++++
 src/nautilus-operations-manager.h   |   17 ++
 6 files changed, 598 insertions(+), 455 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 1aa6064..3171e8d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -272,6 +272,8 @@ nautilus_no_main_sources = \
        nautilus-file-conflict-dialog.c \
        nautilus-file-conflict-dialog.h \
        nautilus-file-operations.c \
+       nautilus-operations-manager.h \
+       nautilus-operations-manager.c \
        nautilus-file-operations.h \
        nautilus-file-private.h \
        nautilus-file-queue.c \
diff --git a/src/nautilus-file-conflict-dialog.c b/src/nautilus-file-conflict-dialog.c
index bfce4c9..0eaa813 100644
--- a/src/nautilus-file-conflict-dialog.c
+++ b/src/nautilus-file-conflict-dialog.c
@@ -35,15 +35,7 @@
 
 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 +44,7 @@ struct _NautilusFileConflictDialogDetails
        GtkWidget *expander;
        GtkWidget *entry;
        GtkWidget *checkbox;
+        GtkWidget *skip_button;
        GtkWidget *rename_button;
        GtkWidget *replace_button;
        GtkWidget *dest_image;
@@ -66,307 +59,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);
-
-       g_free (size);
-       g_free (date);
-       g_free (type);
-       g_free (label_text);
+        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);
+        }
+}
 
-       /* Populate the entry */
-       edit_name = nautilus_file_get_edit_name (dest);
-       details->conflict_name = edit_name;
+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);
+}
 
-       gtk_entry_set_text (GTK_ENTRY (details->entry), edit_name);
+void
+nautilus_file_conflict_dialog_set_conflict_name (NautilusFileConflictDialog *fcd,
+                                                 gchar *conflict_name)
+{
+        NautilusFileConflictDialogDetails *details = fcd->details;
 
-       if (source_is_dir && dest_is_dir) {
-               gtk_button_set_label (GTK_BUTTON (details->replace_button),
-                                     _("Merge"));
-       }
+        details->conflict_name = g_strdup (conflict_name);
 
-       nautilus_file_monitor_add (src, fcd, NAUTILUS_FILE_ATTRIBUTES_FOR_ICON);
-       nautilus_file_monitor_add (dest, fcd, NAUTILUS_FILE_ATTRIBUTES_FOR_ICON);
+        gtk_entry_set_text (GTK_ENTRY (details->entry), details->conflict_name);
 
-       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;
-
-       files = g_list_prepend (files, details->source);
-       files = g_list_prepend (files, details->destination);
-       files = g_list_prepend (files, details->dest_dir);
+        NautilusFileConflictDialogDetails *details = fcd->details;
 
-       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 +363,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 +400,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 +425,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..4d31258 100644
--- a/src/nautilus-file-conflict-dialog.h
+++ b/src/nautilus-file-conflict-dialog.h
@@ -65,10 +65,25 @@ enum
 
 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 1ec5591..7ea2ada 100644
--- a/src/nautilus-file-operations.c
+++ b/src/nautilus-file-operations.c
@@ -51,6 +51,7 @@
 #include <gtk/gtk.h>
 #include <gio/gio.h>
 #include <glib.h>
+#include "nautilus-operations-manager.h"
 #include "nautilus-file-changes-queue.h"
 #include "nautilus-file-private.h"
 #include "nautilus-global-preferences.h"
@@ -4388,117 +4389,33 @@ 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)
+static FileConflictResponse *
+signal_copy_move_conflict (CommonJob *job,
+                          GFile *src,
+                          GFile *dest,
+                          GFile *dest_dir)
 {
-       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)
-{
-       ConflictDialogData *data;
-       ConflictResponseData *resp_data;
+       FileConflictResponse *response;
 
        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);
-
        nautilus_progress_info_pause (job->progress);
 
-       g_mutex_lock (&data->mutex);
-
-       g_main_context_invoke (NULL,
-                              do_run_conflict_dialog,
-                              data);
-
-       while (!data->completed) {
-               g_cond_wait (&data->cond, &data->mutex);
-       }
+       response = get_copy_move_file_conflict_response (job->parent_window,
+                                                         src,
+                                                         dest,
+                                                         dest_dir);
 
        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;
+       return response;
 }
 
 static void
-conflict_response_data_free (ConflictResponseData *data)
+conflict_response_data_free (FileConflictResponse *data)
 {
        g_free (data->new_name);
-       g_slice_free (ConflictResponseData, data);
+       g_slice_free (FileConflictResponse, data);
 }
 
 static GFile *
@@ -4745,7 +4662,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);
 
@@ -4771,7 +4688,7 @@ copy_move_file (CopyMoveJob *copy_job,
                        goto out;
                }
 
-               response = run_conflict_dialog (job, src, dest, dest_dir);      
+               response = signal_copy_move_conflict (job, src, dest, dest_dir);
 
                if (response->id == GTK_RESPONSE_CANCEL ||
                    response->id == GTK_RESPONSE_DELETE_EVENT) {
@@ -5372,7 +5289,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);
 
@@ -5391,7 +5308,7 @@ move_file_prepare (CopyMoveJob *move_job,
                        goto out;
                }
 
-               response = run_conflict_dialog (job, src, dest, dest_dir);
+               response = signal_copy_move_conflict (job, src, dest, dest_dir);
 
                if (response->id == GTK_RESPONSE_CANCEL ||
                    response->id == GTK_RESPONSE_DELETE_EVENT) {
diff --git a/src/nautilus-operations-manager.c b/src/nautilus-operations-manager.c
new file mode 100644
index 0000000..f0bebe9
--- /dev/null
+++ b/src/nautilus-operations-manager.c
@@ -0,0 +1,420 @@
+#include <gio/gio.h>
+#include <glib/gi18n.h>
+
+#include "nautilus-file.h"
+#include "nautilus-file-operations.h"
+#include "nautilus-operations-manager.h"
+#include "nautilus-file-conflict-dialog.h"
+
+typedef struct _FileConflictDialogData FileConflictDialogData;
+typedef void (*FileConflictDialogFunc) (FileConflictDialogData *data);
+
+struct _FileConflictDialogData {
+        GFile *src_name;
+        GFile *dest_name;
+        GFile *dest_dir_name;
+
+        GtkWindow *parent;
+
+        FileConflictResponse *response;
+
+        NautilusFile *source;
+        NautilusFile *destination;
+        NautilusFile *dest_dir;
+
+        NautilusFileConflictDialog *dialog;
+
+        NautilusFileListCallback files_list_ready_cb;
+
+        NautilusFileListHandle *handle;
+        gulong src_handler_id;
+        gulong dest_handler_id;
+        /* Dialogs are ran from operation threads, which need to be blocked until
+         * the user gives a valid response
+         */
+        gboolean completed;
+        GMutex mutex;
+        GCond cond;
+};
+
+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 src_mtime, dest_mtime;
+        g_autofree gchar *message = NULL;
+        g_autofree gchar *dest_name;
+        g_autofree gchar *dest_dir_name;
+        gboolean source_is_dir;
+        gboolean dest_is_dir;
+
+        src_mtime = nautilus_file_get_mtime (data->source);
+        dest_mtime = nautilus_file_get_mtime (data->destination);
+
+        dest_name = nautilus_file_get_display_name (data->destination);
+        dest_dir_name = nautilus_file_get_display_name (data->dest_dir);
+
+        source_is_dir = nautilus_file_is_directory (data->source);
+        dest_is_dir = nautilus_file_is_directory (data->destination);
+
+        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 {
+                        primary_text = g_strdup_printf
+                                (_("Replace folder “%s”?"), dest_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”."),
+                                 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);
+
+        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)
+{
+        char *size, *date, *type = NULL;
+        GString *destination_label;
+        GString *source_label;
+        gboolean source_is_dir, dest_is_dir, should_show_type;
+
+        source_is_dir = nautilus_file_is_directory (data->source);
+        dest_is_dir = nautilus_file_is_directory (data->destination);
+
+        type = nautilus_file_get_mime_type (data->destination);
+        should_show_type = !nautilus_file_is_mime_type (data->source, type);
+
+        g_free (type);
+        type = NULL;
+
+        date = nautilus_file_get_string_attribute (data->destination,
+                                                   "date_modified");
+        size = nautilus_file_get_string_attribute (data->destination, "size");
+
+        if (should_show_type) {
+                type = nautilus_file_get_string_attribute (data->destination, "type");
+        }
+
+        destination_label = g_string_new (NULL);
+        if (dest_is_dir) {
+                g_string_append_printf (destination_label, "<b>%s</b>\n", _("Original folder"));
+                g_string_append_printf (destination_label, "%s %s\n", _("Items:"), size);
+        }
+        else {
+                g_string_append_printf (destination_label, "<b>%s</b>\n", _("Original file"));
+                g_string_append_printf (destination_label, "%s %s\n", _("Size:"), size);
+        }
+
+        if (should_show_type) {
+                g_string_append_printf (destination_label, "%s %s\n", _("Type:"), type);
+        }
+
+        g_string_append_printf (destination_label, "%s %s", _("Last modified:"), date);
+
+        g_free (size);
+        g_free (type);
+        g_free (date);
+
+        date = nautilus_file_get_string_attribute (data->source,
+                                                   "date_modified");
+        size = nautilus_file_get_string_attribute (data->source, "size");
+
+        if (should_show_type) {
+                type = nautilus_file_get_string_attribute (data->source, "type");
+        }
+
+        source_label = g_string_new (NULL);
+        if (source_is_dir) {
+                g_string_append_printf (source_label, "<b>%s</b>\n", dest_is_dir ? _("Merge with") : 
_("Replace with"));
+                g_string_append_printf (source_label, "%s %s\n", _("Items:"), size);
+        }
+        else {
+                g_string_append_printf (source_label, "<b>%s</b>\n", _("Replace with"));
+                g_string_append_printf (source_label, "%s %s\n", _("Size:"), size);
+        }
+
+        if (should_show_type) {
+                g_string_append_printf (source_label, "%s %s\n", _("Type:"), type);
+        }
+
+        g_string_append_printf (source_label, "%s %s", _("Last modified:"), date);
+
+        nautilus_file_conflict_dialog_set_file_labels (data->dialog,
+                                                       destination_label->str,
+                                                       source_label->str);
+
+        g_free (size);
+        g_free (date);
+        g_free (type);
+        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_dir, dest_is_dir;
+
+        source_is_dir = nautilus_file_is_directory (data->source);
+        dest_is_dir = nautilus_file_is_directory (data->destination);
+
+        if (source_is_dir && dest_is_dir) {
+                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_file_list_ready_cb (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->src_handler_id = g_signal_connect (data->source, "changed",
+                          G_CALLBACK (file_icons_changed), data);
+        data->dest_handler_id = g_signal_connect (data->destination, "changed",
+                          G_CALLBACK (file_icons_changed), data);
+}
+
+static void
+build_dialog_appearance (FileConflictDialogData *data)
+{
+        GList *files = NULL;
+
+        files = g_list_prepend (files, data->source);
+        files = g_list_prepend (files, data->destination);
+        files = g_list_prepend (files, data->dest_dir);
+
+        nautilus_file_list_call_when_ready (files,
+                                            NAUTILUS_FILE_ATTRIBUTES_FOR_ICON,
+                                            &data->handle, data->files_list_ready_cb, data);
+        g_list_free (files);
+}
+
+static gboolean
+run_file_conflict_dialog (gpointer _data)
+{
+        FileConflictDialogData *data = _data;
+        int response_id;
+
+        g_mutex_lock (&data->mutex);
+
+        data->source = nautilus_file_get (data->src_name);
+        data->destination = nautilus_file_get (data->dest_name);
+        data->dest_dir = nautilus_file_get (data->dest_dir_name);
+
+        data->dialog = nautilus_file_conflict_dialog_new (data->parent);
+
+        build_dialog_appearance (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->src_handler_id) {
+                g_signal_handler_disconnect (data->source, data->src_handler_id);
+                nautilus_file_monitor_remove (data->source, data);
+        }
+
+        if (data->dest_handler_id) {
+                g_signal_handler_disconnect (data->destination, data->dest_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;
+        data->completed = TRUE;
+
+        gtk_widget_destroy (GTK_WIDGET (data->dialog));
+
+        g_cond_signal (&data->cond);
+        g_mutex_unlock (&data->mutex);
+
+        nautilus_file_unref (data->source);
+        nautilus_file_unref (data->destination);
+        nautilus_file_unref (data->dest_dir);
+
+        return FALSE;
+}
+
+static FileConflictResponse *
+get_file_conflict_response (FileConflictDialogData *data)
+{
+        FileConflictResponse *response;
+
+        response = g_slice_new0 (FileConflictResponse);
+        response->new_name = NULL;
+        data->response = response;
+
+        data->completed = FALSE;
+        g_mutex_init (&data->mutex);
+        g_cond_init (&data->cond);
+
+        g_mutex_lock (&data->mutex);
+
+        g_main_context_invoke (NULL,
+                               run_file_conflict_dialog,
+                               data);
+
+        while (!data->completed) {
+                g_cond_wait (&data->cond, &data->mutex);
+        }
+
+        g_mutex_unlock (&data->mutex);
+        g_mutex_clear (&data->mutex);
+        g_cond_clear (&data->cond);
+
+        g_slice_free (FileConflictDialogData, data);
+
+        return response;
+}
+
+FileConflictResponse *
+get_copy_move_file_conflict_response (GtkWindow *parent_window,
+                                      GFile     *src_name,
+                                      GFile     *dest_name,
+                                      GFile     *dest_dir_name)
+{
+        FileConflictDialogData *data;
+
+        data = g_slice_new0 (FileConflictDialogData);
+        data->parent = parent_window;
+        data->src_name = src_name;
+        data->dest_name = dest_name;
+        data->dest_dir_name = dest_dir_name;
+
+        data->files_list_ready_cb = copy_move_file_list_ready_cb;
+
+        return get_file_conflict_response (data);
+}
diff --git a/src/nautilus-operations-manager.h b/src/nautilus-operations-manager.h
new file mode 100644
index 0000000..84d15d0
--- /dev/null
+++ b/src/nautilus-operations-manager.h
@@ -0,0 +1,17 @@
+#ifndef NAUTILUS_OPERATIONS_MANAGER_H
+#define NAUTILUS_OPERATIONS_MANAGER_H
+
+
+typedef struct {
+    int id;
+    char *new_name;
+    gboolean apply_to_all;
+} FileConflictResponse;
+
+
+FileConflictResponse * get_copy_move_file_conflict_response (GtkWindow *parent_window,
+                                                             GFile     *src,
+                                                             GFile     *dest,
+                                                             GFile     *dest_dir);
+
+#endif



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