nautilus-file-conflict-dialog.c 18.7 KB
Newer Older
1 2 3 4 5
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */

/* nautilus-file-conflict-dialog: dialog that handles file conflicts
   during transfer operations.

6
   Copyright (C) 2008-2010 Cosimo Cecchi
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28

   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, write to the
   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
   
   Authors: Cosimo Cecchi <cosimoc@gnome.org>
*/

#include <config.h>
#include "nautilus-file-conflict-dialog.h"

Cosimo Cecchi's avatar
Cosimo Cecchi committed
29
#include <string.h>
30 31 32
#include <glib-object.h>
#include <gio/gio.h>
#include <glib/gi18n.h>
Cosimo Cecchi's avatar
Cosimo Cecchi committed
33
#include <pango/pango.h>
34 35
#include <eel/eel-vfs-extensions.h>

36 37 38 39 40 41
#include "nautilus-file.h"
#include "nautilus-icon-info.h"

struct _NautilusFileConflictDialogDetails
{
	/* conflicting objects */
42 43 44
	NautilusFile *source;
	NautilusFile *destination;
	NautilusFile *dest_dir;
Cosimo Cecchi's avatar
Cosimo Cecchi committed
45

46
	gchar *conflict_name;
47 48 49
	NautilusFileListHandle *handle;
	gulong src_handler_id;
	gulong dest_handler_id;
50

51
	/* UI objects */
Cosimo Cecchi's avatar
Cosimo Cecchi committed
52
	GtkWidget *titles_vbox;
53 54 55 56
	GtkWidget *first_hbox;
	GtkWidget *second_hbox;
	GtkWidget *expander;
	GtkWidget *entry;
Cosimo Cecchi's avatar
Cosimo Cecchi committed
57 58
	GtkWidget *checkbox;
	GtkWidget *rename_button;
59
	GtkWidget *replace_button;
60 61
	GtkWidget *dest_image;
	GtkWidget *src_image;
62 63 64 65
};

G_DEFINE_TYPE (NautilusFileConflictDialog,
	       nautilus_file_conflict_dialog,
Cosimo Cecchi's avatar
Cosimo Cecchi committed
66
	       GTK_TYPE_DIALOG);
67

68 69 70
#define NAUTILUS_FILE_CONFLICT_DIALOG_GET_PRIVATE(object)		\
	(G_TYPE_INSTANCE_GET_PRIVATE ((object), NAUTILUS_TYPE_FILE_CONFLICT_DIALOG, \
				      NautilusFileConflictDialogDetails))
71

72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
static void
file_icons_changed (NautilusFile *file,
		    NautilusFileConflictDialog *fcd)
{
	GdkPixbuf *pixbuf;

	pixbuf = nautilus_file_get_icon_pixbuf (fcd->details->destination,
						NAUTILUS_ICON_SIZE_LARGE,
						TRUE,
						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_ICON_SIZE_LARGE,
						TRUE,
						NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS);

	gtk_image_set_from_pixbuf (GTK_IMAGE (fcd->details->src_image), pixbuf);
	g_object_unref (pixbuf);
}

95
static void
96 97
file_list_ready_cb (GList *files,
		    gpointer user_data)
98
{
99 100
	NautilusFileConflictDialog *fcd = user_data;
	NautilusFile *src, *dest, *dest_dir;
101
	time_t src_mtime, dest_mtime;
102
	gboolean source_is_dir,	dest_is_dir, should_show_type;
103
	NautilusFileConflictDialogDetails *details;
104 105
	char *primary_text, *message, *secondary_text;
	const gchar *message_extra;
106
	char *dest_name, *dest_dir_name, *edit_name;
107
	char *label_text;
108
	char *size, *date, *type = NULL;
Cosimo Cecchi's avatar
Cosimo Cecchi committed
109
	GdkPixbuf *pixbuf;
110
	GtkWidget *label;
111
	GString *str;
112
	PangoAttrList *attr_list;
113

Cosimo Cecchi's avatar
Cosimo Cecchi committed
114
	details = fcd->details;
115 116 117

	details->handle = NULL;

118 119 120
	dest_dir = g_list_nth_data (files, 0);
	dest = g_list_nth_data (files, 1);
	src = g_list_nth_data (files, 2);
121

122 123 124
	src_mtime = nautilus_file_get_mtime (src);
	dest_mtime = nautilus_file_get_mtime (dest);

125 126
	dest_name = nautilus_file_get_display_name (dest);
	dest_dir_name = nautilus_file_get_display_name (dest_dir);
127

128 129
	source_is_dir = nautilus_file_is_directory (src);
	dest_is_dir = nautilus_file_is_directory (dest);
130

131
	type = nautilus_file_get_mime_type (dest);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
132
	should_show_type = !nautilus_file_is_mime_type (src, type);
133 134 135 136

	g_free (type);
	type = NULL;

137 138 139 140
	/* Set up the right labels */
	if (dest_is_dir) {
		if (source_is_dir) {
			primary_text = g_strdup_printf
Cosimo Cecchi's avatar
Cosimo Cecchi committed
141
				(_("Merge folder \"%s\"?"),
142
				 dest_name);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
143

144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
			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);
			}
161
		} else {
162 163
			message_extra =
				_("Replacing it will remove all files in the folder.");
164
			primary_text = g_strdup_printf
Cosimo Cecchi's avatar
Cosimo Cecchi committed
165
				(_("Replace folder \"%s\"?"), dest_name);
166 167
			message = g_strdup_printf
				(_("A folder with the same name already exists in \"%s\"."),
168 169 170 171
				 dest_dir_name);
		}
	} else {
		primary_text = g_strdup_printf
Cosimo Cecchi's avatar
Cosimo Cecchi committed
172 173
			(_("Replace file \"%s\"?"), dest_name);

174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
		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);
		}
189 190
	}

191 192 193
	secondary_text = g_strdup_printf ("%s\n%s", message, message_extra);
	g_free (message);

194 195 196 197
	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_widget_set_size_request (label, 350, -1);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
198
	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
199
	gtk_box_pack_start (GTK_BOX (details->titles_vbox),
Cosimo Cecchi's avatar
Cosimo Cecchi committed
200
			    label, FALSE, FALSE, 0);
201

202 203 204 205 206 207 208 209
	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);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
210

Cosimo Cecchi's avatar
Cosimo Cecchi committed
211
	label = gtk_label_new (secondary_text);
212 213
	gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
	gtk_widget_set_size_request (label, 350, -1);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
214
	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
215
	gtk_box_pack_start (GTK_BOX (details->titles_vbox),
216
			    label, FALSE, FALSE, 0);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
217
	gtk_widget_show (label);
218 219
	g_free (primary_text);
	g_free (secondary_text);
220

221
	/* Set up file icons */
222
	pixbuf = nautilus_file_get_icon_pixbuf (dest,
Cosimo Cecchi's avatar
Cosimo Cecchi committed
223 224 225
						NAUTILUS_ICON_SIZE_LARGE,
						TRUE,
						NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS);
226
	details->dest_image = gtk_image_new_from_pixbuf (pixbuf);
227
	gtk_box_pack_start (GTK_BOX (details->first_hbox),
228 229
			    details->dest_image, FALSE, FALSE, 0);
	gtk_widget_show (details->dest_image);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
230 231
	g_object_unref (pixbuf);

232
	pixbuf = nautilus_file_get_icon_pixbuf (src,
Cosimo Cecchi's avatar
Cosimo Cecchi committed
233 234 235
						NAUTILUS_ICON_SIZE_LARGE,
						TRUE,
						NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS);
236
	details->src_image = gtk_image_new_from_pixbuf (pixbuf);
237
	gtk_box_pack_start (GTK_BOX (details->second_hbox),
238 239
			    details->src_image, FALSE, FALSE, 0);
	gtk_widget_show (details->src_image);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
240
	g_object_unref (pixbuf);
241 242

	/* Set up labels */
Cosimo Cecchi's avatar
Cosimo Cecchi committed
243
	label = gtk_label_new (NULL);
244
	date = nautilus_file_get_string_attribute (dest,
245
						   "date_modified");
246
	size = nautilus_file_get_string_attribute (dest, "size");
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262

	if (should_show_type) {
		type = nautilus_file_get_string_attribute (dest, "type");
	}

	str = g_string_new (NULL);
	g_string_append_printf (str, "<b>%s</b>\n", _("Original file"));
	g_string_append_printf (str, "<i>%s</i> %s\n", _("Size:"), size);

	if (should_show_type) {
		g_string_append_printf (str, "<i>%s</i> %s\n", _("Type:"), type);
	}

	g_string_append_printf (str, "<i>%s</i> %s", _("Last modified:"), date);

	label_text = str->str;
Cosimo Cecchi's avatar
Cosimo Cecchi committed
263
	gtk_label_set_markup (GTK_LABEL (label),
264
			      label_text);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
265 266 267 268
	gtk_box_pack_start (GTK_BOX (details->first_hbox),
			    label, FALSE, FALSE, 0);
	gtk_widget_show (label);

269
	g_free (size);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
270
	g_free (type);
271
	g_free (date);
272 273 274
	g_string_erase (str, 0, -1);

	/* Second label */
Cosimo Cecchi's avatar
Cosimo Cecchi committed
275
	label = gtk_label_new (NULL);
276
	date = nautilus_file_get_string_attribute (src,
277
						   "date_modified");
278
	size = nautilus_file_get_string_attribute (src, "size");
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293

	if (should_show_type) {
		type = nautilus_file_get_string_attribute (src, "type");
	}

	g_string_append_printf (str, "<b>%s</b>\n", _("Replace with"));
	g_string_append_printf (str, "<i>%s</i> %s\n", _("Size:"), size);

	if (should_show_type) {
		g_string_append_printf (str, "<i>%s</i> %s\n", _("Type:"), type);
	}

	g_string_append_printf (str, "<i>%s</i> %s", _("Last modified:"), date);
	label_text = g_string_free (str, FALSE);

Cosimo Cecchi's avatar
Cosimo Cecchi committed
294
	gtk_label_set_markup (GTK_LABEL (label),
295
			      label_text);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
296 297 298 299
	gtk_box_pack_start (GTK_BOX (details->second_hbox),
			    label, FALSE, FALSE, 0);
	gtk_widget_show (label);

300 301
	g_free (size);
	g_free (date);
302
	g_free (type);
303
	g_free (label_text);
304

305 306 307 308 309 310 311 312 313 314
	/* Populate the entry */
	edit_name = nautilus_file_get_edit_name (dest);
	details->conflict_name = edit_name;

	gtk_entry_set_text (GTK_ENTRY (details->entry), edit_name);

	if (source_is_dir && dest_is_dir) {
		gtk_button_set_label (GTK_BUTTON (details->replace_button),
				      _("Merge"));
	}
315 316 317 318 319 320 321 322

	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);
323 324
}

325 326 327 328
static void
build_dialog_appearance (NautilusFileConflictDialog *fcd)
{
	GList *files = NULL;
329
	NautilusFileConflictDialogDetails *details = fcd->details;
330

331 332 333
	files = g_list_prepend (files, details->source);
	files = g_list_prepend (files, details->destination);
	files = g_list_prepend (files, details->dest_dir);
334 335

	nautilus_file_list_call_when_ready (files,
336 337 338
					    NAUTILUS_FILE_ATTRIBUTES_FOR_ICON,
					    &details->handle, file_list_ready_cb, fcd);
	g_list_free (files);
339 340
}

341 342 343 344 345 346 347 348
static void
set_source_and_destination (GtkWidget *w,
			    GFile *source,
			    GFile *destination,
			    GFile *dest_dir)
{
	NautilusFileConflictDialog *dialog;
	NautilusFileConflictDialogDetails *details;
Cosimo Cecchi's avatar
Cosimo Cecchi committed
349

350 351
	dialog = NAUTILUS_FILE_CONFLICT_DIALOG (w);
	details = dialog->details;
Cosimo Cecchi's avatar
Cosimo Cecchi committed
352

353 354 355
	details->source = nautilus_file_get (source);
	details->destination = nautilus_file_get (destination);
	details->dest_dir = nautilus_file_get (dest_dir);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
356

357 358 359 360
	build_dialog_appearance (dialog);
}

static void
361 362
entry_text_changed_cb (GtkEditable *entry,
		       NautilusFileConflictDialog *dialog)
363 364
{
	NautilusFileConflictDialogDetails *details;
Cosimo Cecchi's avatar
Cosimo Cecchi committed
365 366 367

	details = dialog->details;

368
	/* The rename button is visible only if there's text
Cosimo Cecchi's avatar
Cosimo Cecchi committed
369 370
	 * in the entry.
	 */
371 372 373 374
	if  (g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (entry)), "") != 0 &&
	     g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (entry)), details->conflict_name) != 0) {
		gtk_widget_hide (details->replace_button);
		gtk_widget_show (details->rename_button);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
375 376 377 378 379

		gtk_widget_set_sensitive (details->checkbox, FALSE);

		gtk_dialog_set_default_response (GTK_DIALOG (dialog),
						 CONFLICT_RESPONSE_RENAME);
380 381 382
	} else {
		gtk_widget_hide (details->rename_button);
		gtk_widget_show (details->replace_button);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
383 384 385 386 387

		gtk_widget_set_sensitive (details->checkbox, TRUE);

		gtk_dialog_set_default_response (GTK_DIALOG (dialog),
						 CONFLICT_RESPONSE_REPLACE);
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402
	}
}

static void
expander_activated_cb (GtkExpander *w,
		       NautilusFileConflictDialog *dialog)
{
	NautilusFileConflictDialogDetails *details;
	int start_pos, end_pos;

	details = dialog->details;

	if (!gtk_expander_get_expanded (w)) {
		if (g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (details->entry)),
			       details->conflict_name) == 0) {
Cosimo Cecchi's avatar
Cosimo Cecchi committed
403 404
			gtk_widget_grab_focus (details->entry);

405 406 407 408 409 410
			eel_filename_get_rename_region (details->conflict_name,
							&start_pos, &end_pos);
			gtk_editable_select_region (GTK_EDITABLE (details->entry),
						    start_pos, end_pos);
		}
	}
Cosimo Cecchi's avatar
Cosimo Cecchi committed
411 412 413 414 415 416 417 418 419 420 421 422 423 424
}

static void
checkbox_toggled_cb (GtkToggleButton *t,
		     NautilusFileConflictDialog *dialog)
{
	NautilusFileConflictDialogDetails *details;

	details = dialog->details;

	gtk_widget_set_sensitive (details->expander,
				  !gtk_toggle_button_get_active (t));
	gtk_widget_set_sensitive (details->rename_button,
				  !gtk_toggle_button_get_active (t));
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449

	if  (!gtk_toggle_button_get_active (t) &&
	     g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (details->entry)),
			"") != 0 &&
	     g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (details->entry)),
			details->conflict_name) != 0) {
		gtk_widget_hide (details->replace_button);
		gtk_widget_show (details->rename_button);
	} else {
		gtk_widget_hide (details->rename_button);
		gtk_widget_show (details->replace_button);
	}
}

static void
reset_button_clicked_cb (GtkButton *w,
			 NautilusFileConflictDialog *dialog)
{
	NautilusFileConflictDialogDetails *details;
	int start_pos, end_pos;

	details = dialog->details;

	gtk_entry_set_text (GTK_ENTRY (details->entry),
			    details->conflict_name);
450
	gtk_widget_grab_focus (details->entry);
451 452 453 454 455
	eel_filename_get_rename_region (details->conflict_name,
					&start_pos, &end_pos);
	gtk_editable_select_region (GTK_EDITABLE (details->entry),
				    start_pos, end_pos);

Cosimo Cecchi's avatar
Cosimo Cecchi committed
456 457 458 459 460
}

static void
nautilus_file_conflict_dialog_init (NautilusFileConflictDialog *fcd)
{
461 462
	GtkWidget *hbox, *vbox, *vbox2, *alignment;
	GtkWidget *widget, *dialog_area;
Cosimo Cecchi's avatar
Cosimo Cecchi committed
463 464
	NautilusFileConflictDialogDetails *details;
	GtkDialog *dialog;
Cosimo Cecchi's avatar
Cosimo Cecchi committed
465

Cosimo Cecchi's avatar
Cosimo Cecchi committed
466 467
	details = fcd->details = NAUTILUS_FILE_CONFLICT_DIALOG_GET_PRIVATE (fcd);
	dialog = GTK_DIALOG (fcd);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
468

Cosimo Cecchi's avatar
Cosimo Cecchi committed
469
	/* Setup the main hbox */
Cosimo Cecchi's avatar
Cosimo Cecchi committed
470
	hbox = gtk_hbox_new (FALSE, 12);
471 472 473
	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);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
474

Cosimo Cecchi's avatar
Cosimo Cecchi committed
475 476 477
	/* Setup the dialog image */
	widget = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
					   GTK_ICON_SIZE_DIALOG);
478
	gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
479 480
	gtk_misc_set_alignment (GTK_MISC (widget), 0.5, 0.0);

Cosimo Cecchi's avatar
Cosimo Cecchi committed
481 482
	/* Setup the vbox containing the dialog body */
	vbox = gtk_vbox_new (FALSE, 12);
483
	gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
484

Cosimo Cecchi's avatar
Cosimo Cecchi committed
485
	/* Setup the vbox for the dialog labels */
Cosimo Cecchi's avatar
Cosimo Cecchi committed
486
	widget = gtk_vbox_new (FALSE, 12);
487
	gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
488
	details->titles_vbox = widget;
Cosimo Cecchi's avatar
Cosimo Cecchi committed
489

490
	/* Setup the hboxes to pack file infos into */
491
	alignment = gtk_alignment_new (0.0, 0.0, 0.0, 0.0);
492 493 494 495 496
	g_object_set (alignment, "left-padding", 12, NULL);
	vbox2 = gtk_vbox_new (FALSE, 12);
	gtk_container_add (GTK_CONTAINER (alignment), vbox2);
	gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, FALSE, 0);

Cosimo Cecchi's avatar
Cosimo Cecchi committed
497
	hbox = gtk_hbox_new (FALSE, 12);
498
	gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, FALSE, 0);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
499
	details->first_hbox = hbox;
500

Cosimo Cecchi's avatar
Cosimo Cecchi committed
501
	hbox = gtk_hbox_new (FALSE, 12);
502
	gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, FALSE, 0);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
503
	details->second_hbox = hbox;
Cosimo Cecchi's avatar
Cosimo Cecchi committed
504

505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530
	/* Setup the expander for the rename action */
	details->expander = gtk_expander_new_with_mnemonic (_("_Select a new name for the destination"));
	gtk_box_pack_start (GTK_BOX (vbox2), details->expander, FALSE, FALSE, 0);
	g_signal_connect (details->expander, "activate",
			  G_CALLBACK (expander_activated_cb), dialog);

	hbox = gtk_hbox_new (FALSE, 6);
	gtk_container_add (GTK_CONTAINER (details->expander), hbox);

	widget = gtk_entry_new ();
	gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 6);
	details->entry = widget;
	g_signal_connect (widget, "changed",
			  G_CALLBACK (entry_text_changed_cb), dialog);

	widget = gtk_button_new_with_label (_("Reset"));
	gtk_button_set_image (GTK_BUTTON (widget),
			      gtk_image_new_from_stock (GTK_STOCK_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 (alignment);


Cosimo Cecchi's avatar
Cosimo Cecchi committed
531
	/* Setup the checkbox to apply the action to all files */
Cosimo Cecchi's avatar
Cosimo Cecchi committed
532 533 534
	widget = gtk_check_button_new_with_mnemonic (_("Apply this action to all files"));
	gtk_box_pack_start (GTK_BOX (vbox),
			    widget, FALSE, FALSE, 0);
535
	details->checkbox = widget;
Cosimo Cecchi's avatar
Cosimo Cecchi committed
536
	g_signal_connect (widget, "toggled",
537
			  G_CALLBACK (checkbox_toggled_cb), dialog);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
538

539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555
	/* Add buttons */
	gtk_dialog_add_buttons (dialog,
				GTK_STOCK_CANCEL,
				GTK_RESPONSE_CANCEL,
				_("_Skip"),
				CONFLICT_RESPONSE_SKIP,
				NULL);
	details->rename_button =
		gtk_dialog_add_button (dialog,
				       _("Re_name"),
				       CONFLICT_RESPONSE_RENAME);
	gtk_widget_hide (details->rename_button);

	details->replace_button =
		gtk_dialog_add_button (dialog,
				       _("Replace"),
				       CONFLICT_RESPONSE_REPLACE);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
556
	gtk_widget_grab_focus (details->replace_button);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
557

Cosimo Cecchi's avatar
Cosimo Cecchi committed
558
	/* Setup HIG properties */
559
	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
560
	gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (dialog)), 14);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
561
	gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
562 563 564 565 566 567 568 569 570 571 572 573

	gtk_widget_show_all (dialog_area);
}

static void
do_finalize (GObject *self)
{
	NautilusFileConflictDialogDetails *details =
		NAUTILUS_FILE_CONFLICT_DIALOG (self)->details;

	g_free (details->conflict_name);

574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591
	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);

592
	G_OBJECT_CLASS (nautilus_file_conflict_dialog_parent_class)->finalize (self);
593 594 595 596 597
}

static void
nautilus_file_conflict_dialog_class_init (NautilusFileConflictDialogClass *klass)
{
598 599
	G_OBJECT_CLASS (klass)->finalize = do_finalize;

600 601 602
	g_type_class_add_private (klass, sizeof (NautilusFileConflictDialogDetails));
}

603 604 605 606 607 608 609 610 611 612 613 614 615 616
char *
nautilus_file_conflict_dialog_get_new_name (NautilusFileConflictDialog *dialog)
{
	return g_strdup (gtk_entry_get_text
			 (GTK_ENTRY (dialog->details->entry)));
}

gboolean
nautilus_file_conflict_dialog_get_apply_to_all (NautilusFileConflictDialog *dialog)
{
	return gtk_toggle_button_get_active 
		(GTK_TOGGLE_BUTTON (dialog->details->checkbox));
}

617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635
GtkWidget *
nautilus_file_conflict_dialog_new (GtkWindow *parent,
				   GFile *source,
				   GFile *destination,
				   GFile *dest_dir)
{
	GtkWidget *dialog;
	
	dialog = GTK_WIDGET (g_object_new (NAUTILUS_TYPE_FILE_CONFLICT_DIALOG,
					   "title", _("File conflict"),
					   NULL));
	set_source_and_destination (dialog,
				    source,
				    destination,
				    dest_dir);
	gtk_window_set_transient_for (GTK_WINDOW (dialog),
				      parent);
	return dialog;
}