diff options
Diffstat (limited to 'src/nautilus-file-conflict-dialog.c')
-rw-r--r-- | src/nautilus-file-conflict-dialog.c | 390 |
1 files changed, 390 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..fdcaf2d --- /dev/null +++ b/src/nautilus-file-conflict-dialog.c @@ -0,0 +1,390 @@ +/* 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; + + /* UI objects */ + GtkWidget *titles_vbox; + GtkWidget *first_hbox; + GtkWidget *second_hbox; + GtkWidget *expander; + GtkWidget *entry; + GtkWidget *checkbox; + GtkWidget *skip_button; + GtkWidget *rename_button; + GtkWidget *replace_button; + GtkWidget *dest_image; + GtkWidget *src_image; +}; + +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) +{ + 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 (fcd->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 (fcd->titles_vbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); +} + +void +nautilus_file_conflict_dialog_set_images (NautilusFileConflictDialog *fcd, + GdkPixbuf *destination_pixbuf, + GdkPixbuf *source_pixbuf) +{ + if (fcd->dest_image == NULL) + { + fcd->dest_image = gtk_image_new_from_pixbuf (destination_pixbuf); + gtk_box_pack_start (GTK_BOX (fcd->first_hbox), fcd->dest_image, FALSE, FALSE, 0); + gtk_widget_show (fcd->dest_image); + } + else + { + gtk_image_set_from_pixbuf (GTK_IMAGE (fcd->dest_image), destination_pixbuf); + } + + if (fcd->src_image == NULL) + { + fcd->src_image = gtk_image_new_from_pixbuf (source_pixbuf); + gtk_box_pack_start (GTK_BOX (fcd->second_hbox), fcd->src_image, FALSE, FALSE, 0); + gtk_widget_show (fcd->src_image); + } + else + { + gtk_image_set_from_pixbuf (GTK_IMAGE (fcd->src_image), source_pixbuf); + } +} + +void +nautilus_file_conflict_dialog_set_file_labels (NautilusFileConflictDialog *fcd, + gchar *destination_label, + gchar *source_label) +{ + GtkWidget *label; + + label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (label), destination_label); + gtk_box_pack_start (GTK_BOX (fcd->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 (fcd->second_hbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); +} + +void +nautilus_file_conflict_dialog_set_conflict_name (NautilusFileConflictDialog *fcd, + gchar *conflict_name) +{ + fcd->conflict_name = g_strdup (conflict_name); + + gtk_entry_set_text (GTK_ENTRY (fcd->entry), fcd->conflict_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) +{ + /* The rename button is visible only if there's text + * in the entry. + */ + if (g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (entry)), "") != 0 && + g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (entry)), dialog->conflict_name) != 0) + { + gtk_widget_hide (dialog->replace_button); + gtk_widget_show (dialog->rename_button); + + gtk_widget_set_sensitive (dialog->checkbox, FALSE); + + gtk_dialog_set_default_response (GTK_DIALOG (dialog), CONFLICT_RESPONSE_RENAME); + } + else + { + gtk_widget_hide (dialog->rename_button); + gtk_widget_show (dialog->replace_button); + + gtk_widget_set_sensitive (dialog->checkbox, TRUE); + + gtk_dialog_set_default_response (GTK_DIALOG (dialog), CONFLICT_RESPONSE_REPLACE); + } +} + +static void +expander_activated_cb (GtkExpander *w, + NautilusFileConflictDialog *dialog) +{ + int start_pos, end_pos; + + if (!gtk_expander_get_expanded (w)) + { + if (g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (dialog->entry)), dialog->conflict_name) == 0) + { + 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 +checkbox_toggled_cb (GtkToggleButton *t, + NautilusFileConflictDialog *dialog) +{ + gtk_widget_set_sensitive (dialog->expander, !gtk_toggle_button_get_active (t)); + gtk_widget_set_sensitive (dialog->rename_button, !gtk_toggle_button_get_active (t)); + + if (!gtk_toggle_button_get_active (t) && + g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (dialog->entry)), "") != 0 && + g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (dialog->entry)), dialog->conflict_name) != 0) + { + gtk_widget_hide (dialog->replace_button); + gtk_widget_show (dialog->rename_button); + } + else + { + gtk_widget_hide (dialog->rename_button); + gtk_widget_show (dialog->replace_button); + } +} + +static void +reset_button_clicked_cb (GtkButton *w, + NautilusFileConflictDialog *dialog) +{ + int start_pos, end_pos; + + gtk_entry_set_text (GTK_ENTRY (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) +{ + GtkWidget *hbox, *vbox, *vbox2; + GtkWidget *widget, *dialog_area; + GtkDialog *dialog; + + dialog = GTK_DIALOG (fcd); + + /* Setup the main hbox */ + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); + dialog_area = gtk_dialog_get_content_area (dialog); + gtk_box_pack_start (GTK_BOX (dialog_area), hbox, FALSE, FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (hbox), 6); + + /* Setup the dialog image */ + widget = gtk_image_new_from_icon_name ("dialog-warning", + GTK_ICON_SIZE_DIALOG); + gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0); + gtk_widget_set_valign (widget, GTK_ALIGN_START); + + /* Setup the vbox containing the dialog body */ + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); + gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0); + + /* Setup the vbox for the dialog labels */ + widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); + gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0); + fcd->titles_vbox = widget; + + /* Setup the hboxes to pack file infos into */ + vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); + gtk_widget_set_halign (vbox2, GTK_ALIGN_START); + gtk_widget_set_margin_start (vbox2, 12); + gtk_box_pack_start (GTK_BOX (vbox), vbox2, FALSE, FALSE, 0); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); + gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, FALSE, 0); + fcd->first_hbox = hbox; + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); + gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, FALSE, 0); + fcd->second_hbox = hbox; + + /* Setup the expander for the rename action */ + fcd->expander = gtk_expander_new_with_mnemonic (_("_Select a new name for the destination")); + gtk_box_pack_start (GTK_BOX (vbox2), fcd->expander, FALSE, FALSE, 0); + g_signal_connect (fcd->expander, "activate", + G_CALLBACK (expander_activated_cb), dialog); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); + gtk_container_add (GTK_CONTAINER (fcd->expander), hbox); + + widget = gtk_entry_new (); + gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 6); + fcd->entry = widget; + g_signal_connect (widget, "changed", + G_CALLBACK (entry_text_changed_cb), dialog); + gtk_entry_set_activates_default (GTK_ENTRY (widget), TRUE); + + widget = gtk_button_new_with_label (_("Reset")); + gtk_button_set_image (GTK_BUTTON (widget), + gtk_image_new_from_icon_name ("edit-undo", + GTK_ICON_SIZE_MENU)); + gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 6); + g_signal_connect (widget, "clicked", + G_CALLBACK (reset_button_clicked_cb), dialog); + + gtk_widget_show_all (vbox2); + + /* Setup the checkbox to apply the action to all files */ + widget = gtk_check_button_new_with_mnemonic (_("Apply this action to all files and folders")); + + gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0); + fcd->checkbox = widget; + g_signal_connect (widget, "toggled", + G_CALLBACK (checkbox_toggled_cb), dialog); + + /* Add buttons */ + gtk_dialog_add_button (dialog, _("_Cancel"), GTK_RESPONSE_CANCEL); + + fcd->skip_button = gtk_dialog_add_button (dialog, + _("_Skip"), + CONFLICT_RESPONSE_SKIP); + + fcd->rename_button = gtk_dialog_add_button (dialog, + _("Re_name"), + CONFLICT_RESPONSE_RENAME); + gtk_widget_hide (fcd->rename_button); + + fcd->replace_button = gtk_dialog_add_button (dialog, + _("Re_place"), + CONFLICT_RESPONSE_REPLACE); + gtk_widget_grab_focus (fcd->replace_button); + + /* Setup HIG properties */ + gtk_container_set_border_width (GTK_CONTAINER (dialog), 5); + gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (dialog)), 14); + gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE); + + gtk_widget_show_all (dialog_area); +} + +static void +do_finalize (GObject *self) +{ + NautilusFileConflictDialog *dialog = NAUTILUS_FILE_CONFLICT_DIALOG (self); + + g_free (dialog->conflict_name); + + G_OBJECT_CLASS (nautilus_file_conflict_dialog_parent_class)->finalize (self); +} + +static void +nautilus_file_conflict_dialog_class_init (NautilusFileConflictDialogClass *klass) +{ + G_OBJECT_CLASS (klass)->finalize = do_finalize; +} + +char * +nautilus_file_conflict_dialog_get_new_name (NautilusFileConflictDialog *dialog) +{ + return g_strdup (gtk_entry_get_text (GTK_ENTRY (dialog->entry))); +} + +gboolean +nautilus_file_conflict_dialog_get_apply_to_all (NautilusFileConflictDialog *dialog) +{ + return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->checkbox)); +} + +NautilusFileConflictDialog * +nautilus_file_conflict_dialog_new (GtkWindow *parent) +{ + 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); + + return dialog; +} |