[nautilus/wip/razvan/compression-support: 9/13] file-conflict-dialog: separate file logic from UI management
- From: Răzvan-Mihai Chițu <razvanchitu src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nautilus/wip/razvan/compression-support: 9/13] file-conflict-dialog: separate file logic from UI management
- Date: Fri, 19 Aug 2016 17:50:00 +0000 (UTC)
commit dd886898cc9ee4ee1c4a56a75e02b73d8ecf3c2b
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.
https://bugzilla.gnome.org/show_bug.cgi?id=768646
src/Makefile.am | 2 +
src/nautilus-file-conflict-dialog.c | 472 +++++++++-------------------------
src/nautilus-file-conflict-dialog.h | 23 ++-
src/nautilus-file-operations.c | 146 ++---------
src/nautilus-operations-ui-manager.c | 451 ++++++++++++++++++++++++++++++++
src/nautilus-operations-ui-manager.h | 18 ++
6 files changed, 640 insertions(+), 472 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 652cab7..19e80c4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -279,6 +279,8 @@ nautilus_no_main_sources = \
nautilus-new-folder-dialog-controller.c \
nautilus-new-folder-dialog-controller.h \
nautilus-file-operations.c \
+ nautilus-operations-ui-manager.h \
+ nautilus-operations-ui-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..81e7b1e 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);
+ 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 +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 b55fa09..3b3a6b4 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-ui-manager.h"
#include "nautilus-file-changes-queue.h"
#include "nautilus-file-private.h"
#include "nautilus-global-preferences.h"
@@ -4260,117 +4261,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 *
@@ -4617,7 +4527,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);
@@ -4643,17 +4553,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) {
@@ -4663,13 +4573,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 ();
@@ -5255,7 +5165,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);
@@ -5274,17 +5184,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) {
@@ -5294,13 +5204,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..cfafeb7
--- /dev/null
+++ b/src/nautilus-operations-ui-manager.c
@@ -0,0 +1,451 @@
+#include <gio/gio.h>
+#include <glib/gi18n.h>
+
+#include "nautilus-file.h"
+#include "nautilus-file-operations.h"
+#include "nautilus-operations-ui-manager.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;
+}
+
+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 a 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 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 on_file_list_ready;
+ NautilusFileListHandle *handle;
+ gulong src_handler_id;
+ gulong dest_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 src_mtime;
+ time_t 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)
+{
+ GString *destination_label;
+ GString *source_label;
+ gboolean source_is_dir;
+ gboolean dest_is_dir;
+ 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_dir = nautilus_file_is_directory (data->source);
+ dest_is_dir = 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 (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:"), 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_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:"), 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_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_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->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 gboolean
+run_file_conflict_dialog (gpointer user_data)
+{
+ FileConflictDialogData *data = user_data;
+ int response_id;
+ GList *files = NULL;
+
+ 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);
+
+ 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->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->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;
+
+ gtk_widget_destroy (GTK_WIDGET (data->dialog));
+
+ nautilus_file_unref (data->source);
+ nautilus_file_unref (data->destination);
+ nautilus_file_unref (data->dest_dir);
+ g_list_free (files);
+
+ return G_SOURCE_REMOVE;
+}
+
+FileConflictResponse *
+copy_move_conflict_ask_user_action (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->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..bada0e9
--- /dev/null
+++ b/src/nautilus-operations-ui-manager.h
@@ -0,0 +1,18 @@
+#ifndef NAUTILUS_OPERATIONS_UI_MANAGER
+#define NAUTILUS_OPERATIONS_UI_MANAGER
+
+
+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);
+
+#endif /* NAUTILUS_OPERATIONS_UI_MANAGER */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]