nautilus-file-conflict-dialog.c 19 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
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,
Cosimo Cecchi's avatar
Cosimo Cecchi committed
81
						gtk_widget_get_scale_factor (fcd->details->dest_image),
82 83 84 85 86 87 88 89
						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,
Cosimo Cecchi's avatar
Cosimo Cecchi committed
90
						gtk_widget_get_scale_factor (fcd->details->src_image),
91 92 93 94 95 96
						NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS);

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

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

Cosimo Cecchi's avatar
Cosimo Cecchi committed
116
	details = fcd->details;
117 118 119

	details->handle = NULL;

120 121 122
	dest_dir = g_list_nth_data (files, 0);
	dest = g_list_nth_data (files, 1);
	src = g_list_nth_data (files, 2);
123

124 125 126
	src_mtime = nautilus_file_get_mtime (src);
	dest_mtime = nautilus_file_get_mtime (dest);

127 128
	dest_name = nautilus_file_get_display_name (dest);
	dest_dir_name = nautilus_file_get_display_name (dest_dir);
129

130 131
	source_is_dir = nautilus_file_is_directory (src);
	dest_is_dir = nautilus_file_is_directory (dest);
132

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

	g_free (type);
	type = NULL;

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

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

176 177 178 179
		message_extra = _("Replacing it will overwrite its content.");

		if (src_mtime > dest_mtime) {
			message = g_strdup_printf (
180
				_("An older file with the same name already exists in “%s”."),
181 182 183
				dest_dir_name);
		} else if (src_mtime < dest_mtime) {
			message = g_strdup_printf (
184
				_("A newer file with the same name already exists in “%s”."),
185 186 187
				dest_dir_name);
		} else {
			message = g_strdup_printf (
188
				_("Another file with the same name already exists in “%s”."),
189 190
				dest_dir_name);
		}
191 192
	}

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

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

204 205 206 207 208 209 210 211
	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
212

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

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

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

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

	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"));
257
	g_string_append_printf (str, "%s %s\n", _("Size:"), size);
258 259

	if (should_show_type) {
260
		g_string_append_printf (str, "%s %s\n", _("Type:"), type);
261 262
	}

263
	g_string_append_printf (str, "%s %s", _("Last modified:"), date);
264 265

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

272
	g_free (size);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
273
	g_free (type);
274
	g_free (date);
275 276 277
	g_string_erase (str, 0, -1);

	/* Second label */
Cosimo Cecchi's avatar
Cosimo Cecchi committed
278
	label = gtk_label_new (NULL);
279
	date = nautilus_file_get_string_attribute (src,
280
						   "date_modified");
281
	size = nautilus_file_get_string_attribute (src, "size");
282 283 284 285 286 287

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

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

	if (should_show_type) {
291
		g_string_append_printf (str, "%s %s\n", _("Type:"), type);
292 293
	}

294
	g_string_append_printf (str, "%s %s", _("Last modified:"), date);
295 296
	label_text = g_string_free (str, FALSE);

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

303 304
	g_free (size);
	g_free (date);
305
	g_free (type);
306
	g_free (label_text);
307

308 309 310 311 312 313 314 315 316 317
	/* 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"));
	}
318 319 320 321 322 323 324 325

	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);
326 327
}

328 329 330 331
static void
build_dialog_appearance (NautilusFileConflictDialog *fcd)
{
	GList *files = NULL;
332
	NautilusFileConflictDialogDetails *details = fcd->details;
333

334 335 336
	files = g_list_prepend (files, details->source);
	files = g_list_prepend (files, details->destination);
	files = g_list_prepend (files, details->dest_dir);
337 338

	nautilus_file_list_call_when_ready (files,
339 340 341
					    NAUTILUS_FILE_ATTRIBUTES_FOR_ICON,
					    &details->handle, file_list_ready_cb, fcd);
	g_list_free (files);
342 343
}

344 345 346 347 348 349 350 351
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
352

353 354
	dialog = NAUTILUS_FILE_CONFLICT_DIALOG (w);
	details = dialog->details;
Cosimo Cecchi's avatar
Cosimo Cecchi committed
355

356 357 358
	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
359

360 361 362 363
	build_dialog_appearance (dialog);
}

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

	details = dialog->details;

371
	/* The rename button is visible only if there's text
Cosimo Cecchi's avatar
Cosimo Cecchi committed
372 373
	 * in the entry.
	 */
374 375 376 377
	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
378 379 380 381 382

		gtk_widget_set_sensitive (details->checkbox, FALSE);

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

		gtk_widget_set_sensitive (details->checkbox, TRUE);

		gtk_dialog_set_default_response (GTK_DIALOG (dialog),
						 CONFLICT_RESPONSE_REPLACE);
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
	}
}

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
406 407
			gtk_widget_grab_focus (details->entry);

408 409 410 411 412 413
			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
414 415 416 417 418 419 420 421 422 423 424 425 426 427
}

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));
428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452

	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);
453
	gtk_widget_grab_focus (details->entry);
454 455 456 457 458
	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
459 460 461 462 463
}

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

Cosimo Cecchi's avatar
Cosimo Cecchi committed
469 470
	details = fcd->details = NAUTILUS_FILE_CONFLICT_DIALOG_GET_PRIVATE (fcd);
	dialog = GTK_DIALOG (fcd);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
471

Cosimo Cecchi's avatar
Cosimo Cecchi committed
472
	/* Setup the main hbox */
473
	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
474 475 476
	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
477

Cosimo Cecchi's avatar
Cosimo Cecchi committed
478
	/* Setup the dialog image */
479 480
	widget = gtk_image_new_from_icon_name ("dialog-warning",
					       GTK_ICON_SIZE_DIALOG);
481
	gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
482 483
	gtk_misc_set_alignment (GTK_MISC (widget), 0.5, 0.0);

Cosimo Cecchi's avatar
Cosimo Cecchi committed
484
	/* Setup the vbox containing the dialog body */
485
	vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
486
	gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
487

Cosimo Cecchi's avatar
Cosimo Cecchi committed
488
	/* Setup the vbox for the dialog labels */
489
	widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
490
	gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
491
	details->titles_vbox = widget;
Cosimo Cecchi's avatar
Cosimo Cecchi committed
492

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

500
	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
501
	gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, FALSE, 0);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
502
	details->first_hbox = hbox;
503

504
	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
505
	gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, FALSE, 0);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
506
	details->second_hbox = hbox;
Cosimo Cecchi's avatar
Cosimo Cecchi committed
507

508 509 510 511 512 513
	/* 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);

514
	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
515 516 517
	gtk_container_add (GTK_CONTAINER (details->expander), hbox);

	widget = gtk_entry_new ();
518
	gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 6);
519 520 521 522 523 524
	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),
525 526
			      gtk_image_new_from_icon_name ("edit-undo",
							    GTK_ICON_SIZE_MENU));
527 528 529 530 531 532 533
	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
534
	/* Setup the checkbox to apply the action to all files */
Cosimo Cecchi's avatar
Cosimo Cecchi committed
535 536 537
	widget = gtk_check_button_new_with_mnemonic (_("Apply this action to all files"));
	gtk_box_pack_start (GTK_BOX (vbox),
			    widget, FALSE, FALSE, 0);
538
	details->checkbox = widget;
Cosimo Cecchi's avatar
Cosimo Cecchi committed
539
	g_signal_connect (widget, "toggled",
540
			  G_CALLBACK (checkbox_toggled_cb), dialog);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
541

542 543
	/* Add buttons */
	gtk_dialog_add_buttons (dialog,
544
				_("_Cancel"),
545 546 547 548 549 550 551 552 553 554 555 556 557 558
				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
559
	gtk_widget_grab_focus (details->replace_button);
Cosimo Cecchi's avatar
Cosimo Cecchi committed
560

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

	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);

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

595
	G_OBJECT_CLASS (nautilus_file_conflict_dialog_parent_class)->finalize (self);
596 597 598 599 600
}

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

603 604 605
	g_type_class_add_private (klass, sizeof (NautilusFileConflictDialogDetails));
}

606 607 608 609 610 611 612 613 614 615 616 617 618 619
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));
}

620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638
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;
}