summaryrefslogtreecommitdiffstats
path: root/src/nautilus-file-conflict-dialog.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/nautilus-file-conflict-dialog.c307
1 files changed, 307 insertions, 0 deletions
diff --git a/src/nautilus-file-conflict-dialog.c b/src/nautilus-file-conflict-dialog.c
new file mode 100644
index 0000000..f7c3cc7
--- /dev/null
+++ b/src/nautilus-file-conflict-dialog.c
@@ -0,0 +1,307 @@
+/* nautilus-file-conflict-dialog: dialog that handles file conflicts
+ * during transfer operations.
+ *
+ * Copyright (C) 2008-2010 Cosimo Cecchi
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Cosimo Cecchi <cosimoc@gnome.org>
+ */
+
+#include <config.h>
+#include "nautilus-file-conflict-dialog.h"
+
+#include <string.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <glib/gi18n.h>
+#include <pango/pango.h>
+#include <eel/eel-vfs-extensions.h>
+
+#include "nautilus-file.h"
+#include "nautilus-icon-info.h"
+#include "nautilus-operations-ui-manager.h"
+
+struct _NautilusFileConflictDialog
+{
+ GtkDialog parent_instance;
+
+ gchar *conflict_name;
+ gchar *suggested_name;
+
+ /* UI objects */
+ GtkWidget *primary_label;
+ GtkWidget *secondary_label;
+ GtkWidget *dest_label;
+ GtkWidget *src_label;
+ GtkWidget *expander;
+ GtkWidget *entry;
+ GtkWidget *checkbox;
+ GtkWidget *cancel_button;
+ GtkWidget *skip_button;
+ GtkWidget *rename_button;
+ GtkWidget *replace_button;
+ GtkWidget *dest_icon;
+ GtkWidget *src_icon;
+};
+
+G_DEFINE_TYPE (NautilusFileConflictDialog, nautilus_file_conflict_dialog, GTK_TYPE_DIALOG);
+
+void
+nautilus_file_conflict_dialog_set_text (NautilusFileConflictDialog *fcd,
+ gchar *primary_text,
+ gchar *secondary_text)
+{
+ gtk_label_set_text (GTK_LABEL (fcd->primary_label), primary_text);
+ gtk_label_set_text (GTK_LABEL (fcd->secondary_label), secondary_text);
+}
+
+void
+nautilus_file_conflict_dialog_set_images (NautilusFileConflictDialog *fcd,
+ GdkPaintable *destination_paintable,
+ GdkPaintable *source_paintable)
+{
+ gtk_picture_set_paintable (GTK_PICTURE (fcd->dest_icon), destination_paintable);
+ gtk_picture_set_paintable (GTK_PICTURE (fcd->src_icon), source_paintable);
+}
+
+void
+nautilus_file_conflict_dialog_set_file_labels (NautilusFileConflictDialog *fcd,
+ gchar *destination_label,
+ gchar *source_label)
+{
+ gtk_label_set_markup (GTK_LABEL (fcd->dest_label), destination_label);
+ gtk_label_set_markup (GTK_LABEL (fcd->src_label), source_label);
+}
+
+void
+nautilus_file_conflict_dialog_set_conflict_name (NautilusFileConflictDialog *fcd,
+ gchar *conflict_name)
+{
+ fcd->conflict_name = g_strdup (conflict_name);
+}
+
+void
+nautilus_file_conflict_dialog_set_suggested_name (NautilusFileConflictDialog *fcd,
+ gchar *suggested_name)
+{
+ fcd->suggested_name = g_strdup (suggested_name);
+ gtk_editable_set_text (GTK_EDITABLE (fcd->entry), suggested_name);
+}
+
+void
+nautilus_file_conflict_dialog_set_replace_button_label (NautilusFileConflictDialog *fcd,
+ gchar *label)
+{
+ gtk_button_set_label (GTK_BUTTON (fcd->replace_button), label);
+}
+
+void
+nautilus_file_conflict_dialog_disable_skip (NautilusFileConflictDialog *fcd)
+{
+ gtk_widget_hide (fcd->skip_button);
+}
+
+void
+nautilus_file_conflict_dialog_disable_replace (NautilusFileConflictDialog *fcd)
+{
+ gtk_widget_set_sensitive (fcd->replace_button, FALSE);
+}
+
+void
+nautilus_file_conflict_dialog_disable_apply_to_all (NautilusFileConflictDialog *fcd)
+{
+ gtk_widget_hide (fcd->checkbox);
+}
+
+static void
+entry_text_changed_cb (GtkEditable *entry,
+ NautilusFileConflictDialog *dialog)
+{
+ if (g_strcmp0 (gtk_editable_get_text (GTK_EDITABLE (entry)), "") != 0 &&
+ g_strcmp0 (gtk_editable_get_text (GTK_EDITABLE (entry)), dialog->conflict_name) != 0)
+ {
+ gtk_widget_set_sensitive (dialog->rename_button, TRUE);
+ }
+ else
+ {
+ gtk_widget_set_sensitive (dialog->rename_button, FALSE);
+ }
+}
+
+static int
+get_character_position_after_basename (const gchar *filename)
+{
+ const gchar *extension;
+
+ extension = eel_filename_get_extension_offset (filename);
+
+ if (extension == NULL)
+ {
+ /* If the filename has got no extension, we want the position of the
+ * the terminating null. */
+ return (int) g_utf8_strlen (filename, -1);
+ }
+
+ return g_utf8_pointer_to_offset (filename, extension);
+}
+
+static void
+on_expanded_notify (GtkExpander *w,
+ GParamSpec *pspec,
+ NautilusFileConflictDialog *dialog)
+{
+ if (gtk_expander_get_expanded (w))
+ {
+ gtk_widget_hide (dialog->replace_button);
+ gtk_widget_show (dialog->rename_button);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), CONFLICT_RESPONSE_RENAME);
+
+ gtk_widget_set_sensitive (dialog->checkbox, FALSE);
+
+ gtk_widget_grab_focus (dialog->entry);
+ if (g_strcmp0 (gtk_editable_get_text (GTK_EDITABLE (dialog->entry)), dialog->suggested_name) == 0)
+ {
+ /* The suggested name is in the form "original (1).txt", if the
+ * the conflicting name was "original.txt". The user may want to
+ * replace the "(1)" bits with with something more meaningful, so
+ * select this region for convenience. */
+
+ int start_pos;
+ int end_pos;
+
+ start_pos = get_character_position_after_basename (dialog->conflict_name);
+ end_pos = get_character_position_after_basename (dialog->suggested_name);
+
+ gtk_editable_select_region (GTK_EDITABLE (dialog->entry), start_pos, end_pos);
+ }
+ }
+ else
+ {
+ gtk_widget_hide (dialog->rename_button);
+ gtk_widget_show (dialog->replace_button);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), CONFLICT_RESPONSE_REPLACE);
+
+ gtk_widget_set_sensitive (dialog->checkbox, TRUE);
+ }
+}
+
+static void
+checkbox_toggled_cb (GtkCheckButton *t,
+ NautilusFileConflictDialog *dialog)
+{
+ gtk_widget_set_sensitive (dialog->expander, !gtk_check_button_get_active (t));
+}
+
+static void
+reset_button_clicked_cb (GtkButton *w,
+ NautilusFileConflictDialog *dialog)
+{
+ int start_pos, end_pos;
+
+ gtk_editable_set_text (GTK_EDITABLE (dialog->entry), dialog->conflict_name);
+ gtk_widget_grab_focus (dialog->entry);
+ eel_filename_get_rename_region (dialog->conflict_name, &start_pos, &end_pos);
+ gtk_editable_select_region (GTK_EDITABLE (dialog->entry), start_pos, end_pos);
+}
+
+static void
+nautilus_file_conflict_dialog_init (NautilusFileConflictDialog *fcd)
+{
+ gtk_widget_init_template (GTK_WIDGET (fcd));
+}
+
+static void
+do_finalize (GObject *self)
+{
+ NautilusFileConflictDialog *dialog = NAUTILUS_FILE_CONFLICT_DIALOG (self);
+
+ g_free (dialog->conflict_name);
+ g_free (dialog->suggested_name);
+
+ G_OBJECT_CLASS (nautilus_file_conflict_dialog_parent_class)->finalize (self);
+}
+
+static void
+nautilus_file_conflict_dialog_class_init (NautilusFileConflictDialogClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/nautilus/ui/nautilus-file-conflict-dialog.ui");
+ gtk_widget_class_bind_template_child (widget_class, NautilusFileConflictDialog, primary_label);
+ gtk_widget_class_bind_template_child (widget_class, NautilusFileConflictDialog, secondary_label);
+ gtk_widget_class_bind_template_child (widget_class, NautilusFileConflictDialog, dest_label);
+ gtk_widget_class_bind_template_child (widget_class, NautilusFileConflictDialog, src_label);
+ gtk_widget_class_bind_template_child (widget_class, NautilusFileConflictDialog, expander);
+ gtk_widget_class_bind_template_child (widget_class, NautilusFileConflictDialog, entry);
+ gtk_widget_class_bind_template_child (widget_class, NautilusFileConflictDialog, checkbox);
+ gtk_widget_class_bind_template_child (widget_class, NautilusFileConflictDialog, cancel_button);
+ gtk_widget_class_bind_template_child (widget_class, NautilusFileConflictDialog, rename_button);
+ gtk_widget_class_bind_template_child (widget_class, NautilusFileConflictDialog, replace_button);
+ gtk_widget_class_bind_template_child (widget_class, NautilusFileConflictDialog, skip_button);
+ gtk_widget_class_bind_template_child (widget_class, NautilusFileConflictDialog, dest_icon);
+ gtk_widget_class_bind_template_child (widget_class, NautilusFileConflictDialog, src_icon);
+ gtk_widget_class_bind_template_callback (widget_class, entry_text_changed_cb);
+ gtk_widget_class_bind_template_callback (widget_class, on_expanded_notify);
+ gtk_widget_class_bind_template_callback (widget_class, checkbox_toggled_cb);
+ gtk_widget_class_bind_template_callback (widget_class, reset_button_clicked_cb);
+
+ G_OBJECT_CLASS (klass)->finalize = do_finalize;
+}
+
+static gboolean
+activate_buttons (NautilusFileConflictDialog *fcd)
+{
+ gtk_widget_set_sensitive (GTK_WIDGET (fcd->cancel_button), TRUE);
+ gtk_widget_set_sensitive (GTK_WIDGET (fcd->skip_button), TRUE);
+ gtk_widget_set_sensitive (GTK_WIDGET (fcd->rename_button), TRUE);
+ gtk_widget_set_sensitive (GTK_WIDGET (fcd->replace_button), TRUE);
+ gtk_widget_set_sensitive (GTK_WIDGET (fcd->expander), TRUE);
+ return G_SOURCE_REMOVE;
+}
+
+void
+nautilus_file_conflict_dialog_delay_buttons_activation (NautilusFileConflictDialog *fcd)
+{
+ gtk_widget_set_sensitive (GTK_WIDGET (fcd->cancel_button), FALSE);
+ gtk_widget_set_sensitive (GTK_WIDGET (fcd->skip_button), FALSE);
+ gtk_widget_set_sensitive (GTK_WIDGET (fcd->rename_button), FALSE);
+ gtk_widget_set_sensitive (GTK_WIDGET (fcd->replace_button), FALSE);
+ gtk_widget_set_sensitive (GTK_WIDGET (fcd->expander), FALSE);
+
+ g_timeout_add_seconds (BUTTON_ACTIVATION_DELAY_IN_SECONDS,
+ G_SOURCE_FUNC (activate_buttons),
+ fcd);
+}
+
+char *
+nautilus_file_conflict_dialog_get_new_name (NautilusFileConflictDialog *dialog)
+{
+ return g_strdup (gtk_editable_get_text (GTK_EDITABLE (dialog->entry)));
+}
+
+gboolean
+nautilus_file_conflict_dialog_get_apply_to_all (NautilusFileConflictDialog *dialog)
+{
+ return gtk_check_button_get_active (GTK_CHECK_BUTTON (dialog->checkbox));
+}
+
+NautilusFileConflictDialog *
+nautilus_file_conflict_dialog_new (GtkWindow *parent)
+{
+ return NAUTILUS_FILE_CONFLICT_DIALOG (g_object_new (NAUTILUS_TYPE_FILE_CONFLICT_DIALOG,
+ "transient-for", parent,
+ "use-header-bar", TRUE,
+ NULL));
+}