/* 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 .
*
* Authors: Cosimo Cecchi
*/
#include
#include "nautilus-file-conflict-dialog.h"
#include
#include
#include
#include
#include
#include
#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));
}