nautilus-3.6.3/libnautilus-private/nautilus-file-conflict-dialog.c

No issues found

  1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
  2 
  3 /* nautilus-file-conflict-dialog: dialog that handles file conflicts
  4    during transfer operations.
  5 
  6    Copyright (C) 2008-2010 Cosimo Cecchi
  7 
  8    This program is free software; you can redistribute it and/or
  9    modify it under the terms of the GNU General Public License as
 10    published by the Free Software Foundation; either version 2 of the
 11    License, or (at your option) any later version.
 12    
 13    This program is distributed in the hope that it will be useful,
 14    but WITHOUT ANY WARRANTY; without even the implied warranty of
 15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 16    General Public License for more details.
 17    
 18    You should have received a copy of the GNU General Public
 19    License along with this program; if not, write to the
 20    Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 21    Boston, MA 02111-1307, USA.
 22    
 23    Authors: Cosimo Cecchi <cosimoc@gnome.org>
 24 */
 25 
 26 #include <config.h>
 27 #include "nautilus-file-conflict-dialog.h"
 28 
 29 #include <string.h>
 30 #include <glib-object.h>
 31 #include <gio/gio.h>
 32 #include <glib/gi18n.h>
 33 #include <pango/pango.h>
 34 #include <eel/eel-vfs-extensions.h>
 35 
 36 #include "nautilus-file.h"
 37 #include "nautilus-icon-info.h"
 38 
 39 struct _NautilusFileConflictDialogDetails
 40 {
 41 	/* conflicting objects */
 42 	NautilusFile *source;
 43 	NautilusFile *destination;
 44 	NautilusFile *dest_dir;
 45 
 46 	gchar *conflict_name;
 47 	NautilusFileListHandle *handle;
 48 	gulong src_handler_id;
 49 	gulong dest_handler_id;
 50 
 51 	/* UI objects */
 52 	GtkWidget *titles_vbox;
 53 	GtkWidget *first_hbox;
 54 	GtkWidget *second_hbox;
 55 	GtkWidget *expander;
 56 	GtkWidget *entry;
 57 	GtkWidget *checkbox;
 58 	GtkWidget *rename_button;
 59 	GtkWidget *replace_button;
 60 	GtkWidget *dest_image;
 61 	GtkWidget *src_image;
 62 };
 63 
 64 G_DEFINE_TYPE (NautilusFileConflictDialog,
 65 	       nautilus_file_conflict_dialog,
 66 	       GTK_TYPE_DIALOG);
 67 
 68 #define NAUTILUS_FILE_CONFLICT_DIALOG_GET_PRIVATE(object)		\
 69 	(G_TYPE_INSTANCE_GET_PRIVATE ((object), NAUTILUS_TYPE_FILE_CONFLICT_DIALOG, \
 70 				      NautilusFileConflictDialogDetails))
 71 
 72 static void
 73 file_icons_changed (NautilusFile *file,
 74 		    NautilusFileConflictDialog *fcd)
 75 {
 76 	GdkPixbuf *pixbuf;
 77 
 78 	pixbuf = nautilus_file_get_icon_pixbuf (fcd->details->destination,
 79 						NAUTILUS_ICON_SIZE_LARGE,
 80 						TRUE,
 81 						NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS);
 82 
 83 	gtk_image_set_from_pixbuf (GTK_IMAGE (fcd->details->dest_image), pixbuf);
 84 	g_object_unref (pixbuf);
 85 
 86 	pixbuf = nautilus_file_get_icon_pixbuf (fcd->details->source,
 87 						NAUTILUS_ICON_SIZE_LARGE,
 88 						TRUE,
 89 						NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS);
 90 
 91 	gtk_image_set_from_pixbuf (GTK_IMAGE (fcd->details->src_image), pixbuf);
 92 	g_object_unref (pixbuf);
 93 }
 94 
 95 static void
 96 file_list_ready_cb (GList *files,
 97 		    gpointer user_data)
 98 {
 99 	NautilusFileConflictDialog *fcd = user_data;
100 	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 	char *primary_text, *message, *secondary_text;
105 	const gchar *message_extra;
106 	char *dest_name, *dest_dir_name, *edit_name;
107 	char *label_text;
108 	char *size, *date, *type = NULL;
109 	GdkPixbuf *pixbuf;
110 	GtkWidget *label;
111 	GString *str;
112 	PangoAttrList *attr_list;
113 
114 	details = fcd->details;
115 
116 	details->handle = NULL;
117 
118 	dest_dir = g_list_nth_data (files, 0);
119 	dest = g_list_nth_data (files, 1);
120 	src = g_list_nth_data (files, 2);
121 
122 	src_mtime = nautilus_file_get_mtime (src);
123 	dest_mtime = nautilus_file_get_mtime (dest);
124 
125 	dest_name = nautilus_file_get_display_name (dest);
126 	dest_dir_name = nautilus_file_get_display_name (dest_dir);
127 
128 	source_is_dir = nautilus_file_is_directory (src);
129 	dest_is_dir = nautilus_file_is_directory (dest);
130 
131 	type = nautilus_file_get_mime_type (dest);
132 	should_show_type = !nautilus_file_is_mime_type (src, type);
133 
134 	g_free (type);
135 	type = NULL;
136 
137 	/* Set up the right labels */
138 	if (dest_is_dir) {
139 		if (source_is_dir) {
140 			primary_text = g_strdup_printf
141 				(_("Merge folder “%s”?"),
142 				 dest_name);
143 
144 			message_extra = 
145 				_("Merging will ask for confirmation before replacing any files in "
146 				  "the folder that conflict with the files being copied.");
147 
148 			if (src_mtime > dest_mtime) {
149 				message = g_strdup_printf (
150 					_("An older folder with the same name already exists in “%s”."),
151 					dest_dir_name);
152 			} else if (src_mtime < dest_mtime) {
153 				message = g_strdup_printf (
154 					_("A newer folder with the same name already exists in “%s”."),
155 					dest_dir_name);
156 			} else {
157 				message = g_strdup_printf (
158 					_("Another folder with the same name already exists in “%s”."),
159 					dest_dir_name);
160 			}
161 		} else {
162 			message_extra =
163 				_("Replacing it will remove all files in the folder.");
164 			primary_text = g_strdup_printf
165 				(_("Replace folder “%s”?"), dest_name);
166 			message = g_strdup_printf
167 				(_("A folder with the same name already exists in “%s”."),
168 				 dest_dir_name);
169 		}
170 	} else {
171 		primary_text = g_strdup_printf
172 			(_("Replace file “%s”?"), dest_name);
173 
174 		message_extra = _("Replacing it will overwrite its content.");
175 
176 		if (src_mtime > dest_mtime) {
177 			message = g_strdup_printf (
178 				_("An older file with the same name already exists in “%s”."),
179 				dest_dir_name);
180 		} else if (src_mtime < dest_mtime) {
181 			message = g_strdup_printf (
182 				_("A newer file with the same name already exists in “%s”."),
183 				dest_dir_name);
184 		} else {
185 			message = g_strdup_printf (
186 				_("Another file with the same name already exists in “%s”."),
187 				dest_dir_name);
188 		}
189 	}
190 
191 	secondary_text = g_strdup_printf ("%s\n%s", message, message_extra);
192 	g_free (message);
193 
194 	label = gtk_label_new (primary_text);
195 	gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
196 	gtk_label_set_line_wrap_mode (GTK_LABEL (label), PANGO_WRAP_WORD_CHAR);
197 	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
198 	gtk_box_pack_start (GTK_BOX (details->titles_vbox),
199 			    label, FALSE, FALSE, 0);
200 	gtk_widget_show (label);
201 
202 	attr_list = pango_attr_list_new ();
203 	pango_attr_list_insert (attr_list, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
204 	pango_attr_list_insert (attr_list, pango_attr_scale_new (PANGO_SCALE_LARGE));
205 	g_object_set (label,
206 		      "attributes", attr_list,
207 		      NULL);
208 
209 	pango_attr_list_unref (attr_list);
210 
211 	label = gtk_label_new (secondary_text);
212 	gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
213 	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
214 	gtk_box_pack_start (GTK_BOX (details->titles_vbox),
215 			    label, FALSE, FALSE, 0);
216 	gtk_widget_show (label);
217 	g_free (primary_text);
218 	g_free (secondary_text);
219 
220 	/* Set up file icons */
221 	pixbuf = nautilus_file_get_icon_pixbuf (dest,
222 						NAUTILUS_ICON_SIZE_LARGE,
223 						TRUE,
224 						NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS);
225 	details->dest_image = gtk_image_new_from_pixbuf (pixbuf);
226 	gtk_box_pack_start (GTK_BOX (details->first_hbox),
227 			    details->dest_image, FALSE, FALSE, 0);
228 	gtk_widget_show (details->dest_image);
229 	g_object_unref (pixbuf);
230 
231 	pixbuf = nautilus_file_get_icon_pixbuf (src,
232 						NAUTILUS_ICON_SIZE_LARGE,
233 						TRUE,
234 						NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS);
235 	details->src_image = gtk_image_new_from_pixbuf (pixbuf);
236 	gtk_box_pack_start (GTK_BOX (details->second_hbox),
237 			    details->src_image, FALSE, FALSE, 0);
238 	gtk_widget_show (details->src_image);
239 	g_object_unref (pixbuf);
240 
241 	/* Set up labels */
242 	label = gtk_label_new (NULL);
243 	date = nautilus_file_get_string_attribute (dest,
244 						   "date_modified");
245 	size = nautilus_file_get_string_attribute (dest, "size");
246 
247 	if (should_show_type) {
248 		type = nautilus_file_get_string_attribute (dest, "type");
249 	}
250 
251 	str = g_string_new (NULL);
252 	g_string_append_printf (str, "<b>%s</b>\n", _("Original file"));
253 	g_string_append_printf (str, "%s %s\n", _("Size:"), size);
254 
255 	if (should_show_type) {
256 		g_string_append_printf (str, "%s %s\n", _("Type:"), type);
257 	}
258 
259 	g_string_append_printf (str, "%s %s", _("Last modified:"), date);
260 
261 	label_text = str->str;
262 	gtk_label_set_markup (GTK_LABEL (label),
263 			      label_text);
264 	gtk_box_pack_start (GTK_BOX (details->first_hbox),
265 			    label, FALSE, FALSE, 0);
266 	gtk_widget_show (label);
267 
268 	g_free (size);
269 	g_free (type);
270 	g_free (date);
271 	g_string_erase (str, 0, -1);
272 
273 	/* Second label */
274 	label = gtk_label_new (NULL);
275 	date = nautilus_file_get_string_attribute (src,
276 						   "date_modified");
277 	size = nautilus_file_get_string_attribute (src, "size");
278 
279 	if (should_show_type) {
280 		type = nautilus_file_get_string_attribute (src, "type");
281 	}
282 
283 	g_string_append_printf (str, "<b>%s</b>\n", _("Replace with"));
284 	g_string_append_printf (str, "%s %s\n", _("Size:"), size);
285 
286 	if (should_show_type) {
287 		g_string_append_printf (str, "%s %s\n", _("Type:"), type);
288 	}
289 
290 	g_string_append_printf (str, "%s %s", _("Last modified:"), date);
291 	label_text = g_string_free (str, FALSE);
292 
293 	gtk_label_set_markup (GTK_LABEL (label),
294 			      label_text);
295 	gtk_box_pack_start (GTK_BOX (details->second_hbox),
296 			    label, FALSE, FALSE, 0);
297 	gtk_widget_show (label);
298 
299 	g_free (size);
300 	g_free (date);
301 	g_free (type);
302 	g_free (label_text);
303 
304 	/* Populate the entry */
305 	edit_name = nautilus_file_get_edit_name (dest);
306 	details->conflict_name = edit_name;
307 
308 	gtk_entry_set_text (GTK_ENTRY (details->entry), edit_name);
309 
310 	if (source_is_dir && dest_is_dir) {
311 		gtk_button_set_label (GTK_BUTTON (details->replace_button),
312 				      _("Merge"));
313 	}
314 
315 	nautilus_file_monitor_add (src, fcd, NAUTILUS_FILE_ATTRIBUTES_FOR_ICON);
316 	nautilus_file_monitor_add (dest, fcd, NAUTILUS_FILE_ATTRIBUTES_FOR_ICON);
317 
318 	details->src_handler_id = g_signal_connect (src, "changed",
319 			  G_CALLBACK (file_icons_changed), fcd);
320 	details->dest_handler_id = g_signal_connect (dest, "changed",
321 			  G_CALLBACK (file_icons_changed), fcd);
322 }
323 
324 static void
325 build_dialog_appearance (NautilusFileConflictDialog *fcd)
326 {
327 	GList *files = NULL;
328 	NautilusFileConflictDialogDetails *details = fcd->details;
329 
330 	files = g_list_prepend (files, details->source);
331 	files = g_list_prepend (files, details->destination);
332 	files = g_list_prepend (files, details->dest_dir);
333 
334 	nautilus_file_list_call_when_ready (files,
335 					    NAUTILUS_FILE_ATTRIBUTES_FOR_ICON,
336 					    &details->handle, file_list_ready_cb, fcd);
337 	g_list_free (files);
338 }
339 
340 static void
341 set_source_and_destination (GtkWidget *w,
342 			    GFile *source,
343 			    GFile *destination,
344 			    GFile *dest_dir)
345 {
346 	NautilusFileConflictDialog *dialog;
347 	NautilusFileConflictDialogDetails *details;
348 
349 	dialog = NAUTILUS_FILE_CONFLICT_DIALOG (w);
350 	details = dialog->details;
351 
352 	details->source = nautilus_file_get (source);
353 	details->destination = nautilus_file_get (destination);
354 	details->dest_dir = nautilus_file_get (dest_dir);
355 
356 	build_dialog_appearance (dialog);
357 }
358 
359 static void
360 entry_text_changed_cb (GtkEditable *entry,
361 		       NautilusFileConflictDialog *dialog)
362 {
363 	NautilusFileConflictDialogDetails *details;
364 
365 	details = dialog->details;
366 
367 	/* The rename button is visible only if there's text
368 	 * in the entry.
369 	 */
370 	if  (g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (entry)), "") != 0 &&
371 	     g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (entry)), details->conflict_name) != 0) {
372 		gtk_widget_hide (details->replace_button);
373 		gtk_widget_show (details->rename_button);
374 
375 		gtk_widget_set_sensitive (details->checkbox, FALSE);
376 
377 		gtk_dialog_set_default_response (GTK_DIALOG (dialog),
378 						 CONFLICT_RESPONSE_RENAME);
379 	} else {
380 		gtk_widget_hide (details->rename_button);
381 		gtk_widget_show (details->replace_button);
382 
383 		gtk_widget_set_sensitive (details->checkbox, TRUE);
384 
385 		gtk_dialog_set_default_response (GTK_DIALOG (dialog),
386 						 CONFLICT_RESPONSE_REPLACE);
387 	}
388 }
389 
390 static void
391 expander_activated_cb (GtkExpander *w,
392 		       NautilusFileConflictDialog *dialog)
393 {
394 	NautilusFileConflictDialogDetails *details;
395 	int start_pos, end_pos;
396 
397 	details = dialog->details;
398 
399 	if (!gtk_expander_get_expanded (w)) {
400 		if (g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (details->entry)),
401 			       details->conflict_name) == 0) {
402 			gtk_widget_grab_focus (details->entry);
403 
404 			eel_filename_get_rename_region (details->conflict_name,
405 							&start_pos, &end_pos);
406 			gtk_editable_select_region (GTK_EDITABLE (details->entry),
407 						    start_pos, end_pos);
408 		}
409 	}
410 }
411 
412 static void
413 checkbox_toggled_cb (GtkToggleButton *t,
414 		     NautilusFileConflictDialog *dialog)
415 {
416 	NautilusFileConflictDialogDetails *details;
417 
418 	details = dialog->details;
419 
420 	gtk_widget_set_sensitive (details->expander,
421 				  !gtk_toggle_button_get_active (t));
422 	gtk_widget_set_sensitive (details->rename_button,
423 				  !gtk_toggle_button_get_active (t));
424 
425 	if  (!gtk_toggle_button_get_active (t) &&
426 	     g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (details->entry)),
427 			"") != 0 &&
428 	     g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (details->entry)),
429 			details->conflict_name) != 0) {
430 		gtk_widget_hide (details->replace_button);
431 		gtk_widget_show (details->rename_button);
432 	} else {
433 		gtk_widget_hide (details->rename_button);
434 		gtk_widget_show (details->replace_button);
435 	}
436 }
437 
438 static void
439 reset_button_clicked_cb (GtkButton *w,
440 			 NautilusFileConflictDialog *dialog)
441 {
442 	NautilusFileConflictDialogDetails *details;
443 	int start_pos, end_pos;
444 
445 	details = dialog->details;
446 
447 	gtk_entry_set_text (GTK_ENTRY (details->entry),
448 			    details->conflict_name);
449 	gtk_widget_grab_focus (details->entry);
450 	eel_filename_get_rename_region (details->conflict_name,
451 					&start_pos, &end_pos);
452 	gtk_editable_select_region (GTK_EDITABLE (details->entry),
453 				    start_pos, end_pos);
454 
455 }
456 
457 static void
458 nautilus_file_conflict_dialog_init (NautilusFileConflictDialog *fcd)
459 {
460 	GtkWidget *hbox, *vbox, *vbox2, *alignment;
461 	GtkWidget *widget, *dialog_area;
462 	NautilusFileConflictDialogDetails *details;
463 	GtkDialog *dialog;
464 
465 	details = fcd->details = NAUTILUS_FILE_CONFLICT_DIALOG_GET_PRIVATE (fcd);
466 	dialog = GTK_DIALOG (fcd);
467 
468 	/* Setup the main hbox */
469 	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
470 	dialog_area = gtk_dialog_get_content_area (dialog);
471 	gtk_box_pack_start (GTK_BOX (dialog_area), hbox, FALSE, FALSE, 0);
472 	gtk_container_set_border_width (GTK_CONTAINER (hbox), 6);
473 
474 	/* Setup the dialog image */
475 	widget = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
476 					   GTK_ICON_SIZE_DIALOG);
477 	gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
478 	gtk_misc_set_alignment (GTK_MISC (widget), 0.5, 0.0);
479 
480 	/* Setup the vbox containing the dialog body */
481 	vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
482 	gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
483 
484 	/* Setup the vbox for the dialog labels */
485 	widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
486 	gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
487 	details->titles_vbox = widget;
488 
489 	/* Setup the hboxes to pack file infos into */
490 	alignment = gtk_alignment_new (0.0, 0.0, 0.0, 0.0);
491 	g_object_set (alignment, "left-padding", 12, NULL);
492 	vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
493 	gtk_container_add (GTK_CONTAINER (alignment), vbox2);
494 	gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, FALSE, 0);
495 
496 	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
497 	gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, FALSE, 0);
498 	details->first_hbox = hbox;
499 
500 	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
501 	gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, FALSE, 0);
502 	details->second_hbox = hbox;
503 
504 	/* Setup the expander for the rename action */
505 	details->expander = gtk_expander_new_with_mnemonic (_("_Select a new name for the destination"));
506 	gtk_box_pack_start (GTK_BOX (vbox2), details->expander, FALSE, FALSE, 0);
507 	g_signal_connect (details->expander, "activate",
508 			  G_CALLBACK (expander_activated_cb), dialog);
509 
510 	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
511 	gtk_container_add (GTK_CONTAINER (details->expander), hbox);
512 
513 	widget = gtk_entry_new ();
514 	gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 6);
515 	details->entry = widget;
516 	g_signal_connect (widget, "changed",
517 			  G_CALLBACK (entry_text_changed_cb), dialog);
518 
519 	widget = gtk_button_new_with_label (_("Reset"));
520 	gtk_button_set_image (GTK_BUTTON (widget),
521 			      gtk_image_new_from_stock (GTK_STOCK_UNDO,
522 							GTK_ICON_SIZE_MENU));
523 	gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 6);
524 	g_signal_connect (widget, "clicked",
525 			  G_CALLBACK (reset_button_clicked_cb), dialog);
526 
527 	gtk_widget_show_all (alignment);
528 
529 
530 	/* Setup the checkbox to apply the action to all files */
531 	widget = gtk_check_button_new_with_mnemonic (_("Apply this action to all files"));
532 	gtk_box_pack_start (GTK_BOX (vbox),
533 			    widget, FALSE, FALSE, 0);
534 	details->checkbox = widget;
535 	g_signal_connect (widget, "toggled",
536 			  G_CALLBACK (checkbox_toggled_cb), dialog);
537 
538 	/* Add buttons */
539 	gtk_dialog_add_buttons (dialog,
540 				GTK_STOCK_CANCEL,
541 				GTK_RESPONSE_CANCEL,
542 				_("_Skip"),
543 				CONFLICT_RESPONSE_SKIP,
544 				NULL);
545 	details->rename_button =
546 		gtk_dialog_add_button (dialog,
547 				       _("Re_name"),
548 				       CONFLICT_RESPONSE_RENAME);
549 	gtk_widget_hide (details->rename_button);
550 
551 	details->replace_button =
552 		gtk_dialog_add_button (dialog,
553 				       _("Replace"),
554 				       CONFLICT_RESPONSE_REPLACE);
555 	gtk_widget_grab_focus (details->replace_button);
556 
557 	/* Setup HIG properties */
558 	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
559 	gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (dialog)), 14);
560 	gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
561 
562 	gtk_widget_show_all (dialog_area);
563 }
564 
565 static void
566 do_finalize (GObject *self)
567 {
568 	NautilusFileConflictDialogDetails *details =
569 		NAUTILUS_FILE_CONFLICT_DIALOG (self)->details;
570 
571 	g_free (details->conflict_name);
572 
573 	if (details->handle != NULL) {
574 		nautilus_file_list_cancel_call_when_ready (details->handle);
575 	}
576 
577 	if (details->src_handler_id) {
578 		g_signal_handler_disconnect (details->source, details->src_handler_id);
579 		nautilus_file_monitor_remove (details->source, self);
580 	}
581 
582 	if (details->dest_handler_id) {
583 		g_signal_handler_disconnect (details->destination, details->dest_handler_id);
584 		nautilus_file_monitor_remove (details->destination, self);
585 	}
586 
587 	nautilus_file_unref (details->source);
588 	nautilus_file_unref (details->destination);
589 	nautilus_file_unref (details->dest_dir);
590 
591 	G_OBJECT_CLASS (nautilus_file_conflict_dialog_parent_class)->finalize (self);
592 }
593 
594 static void
595 nautilus_file_conflict_dialog_class_init (NautilusFileConflictDialogClass *klass)
596 {
597 	G_OBJECT_CLASS (klass)->finalize = do_finalize;
598 
599 	g_type_class_add_private (klass, sizeof (NautilusFileConflictDialogDetails));
600 }
601 
602 char *
603 nautilus_file_conflict_dialog_get_new_name (NautilusFileConflictDialog *dialog)
604 {
605 	return g_strdup (gtk_entry_get_text
606 			 (GTK_ENTRY (dialog->details->entry)));
607 }
608 
609 gboolean
610 nautilus_file_conflict_dialog_get_apply_to_all (NautilusFileConflictDialog *dialog)
611 {
612 	return gtk_toggle_button_get_active 
613 		(GTK_TOGGLE_BUTTON (dialog->details->checkbox));
614 }
615 
616 GtkWidget *
617 nautilus_file_conflict_dialog_new (GtkWindow *parent,
618 				   GFile *source,
619 				   GFile *destination,
620 				   GFile *dest_dir)
621 {
622 	GtkWidget *dialog;
623 	
624 	dialog = GTK_WIDGET (g_object_new (NAUTILUS_TYPE_FILE_CONFLICT_DIALOG,
625 					   "title", _("File conflict"),
626 					   NULL));
627 	set_source_and_destination (dialog,
628 				    source,
629 				    destination,
630 				    dest_dir);
631 	gtk_window_set_transient_for (GTK_WINDOW (dialog),
632 				      parent);
633 	return dialog;
634 }