1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3 /* caja-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., 51 Franklin St, Fifth Floor,
21 Boston, MA 02110-1301, USA.
22
23 Authors: Cosimo Cecchi <cosimoc@gnome.org>
24 */
25
26 #include <config.h>
27 #include <string.h>
28 #include <glib-object.h>
29 #include <gio/gio.h>
30 #include <glib/gi18n.h>
31 #include <pango/pango.h>
32
33 #include <eel/eel-vfs-extensions.h>
34 #include <eel/eel-stock-dialogs.h>
35
36 #include "caja-file-conflict-dialog.h"
37 #include "caja-file.h"
38 #include "caja-icon-info.h"
39
40 struct _CajaFileConflictDialogPrivate
41 {
42 /* conflicting objects */
43 CajaFile *source;
44 CajaFile *destination;
45 CajaFile *dest_dir;
46
47 gchar *conflict_name;
48 CajaFileListHandle *handle;
49 gulong src_handler_id;
50 gulong dest_handler_id;
51
52 /* UI objects */
53 GtkWidget *titles_vbox;
54 GtkWidget *first_hbox;
55 GtkWidget *second_hbox;
56 GtkWidget *expander;
57 GtkWidget *entry;
58 GtkWidget *checkbox;
59 GtkWidget *rename_button;
60 GtkWidget *diff_button;
61 GtkWidget *replace_button;
62 GtkWidget *dest_image;
63 GtkWidget *src_image;
64 };
65
66 G_DEFINE_TYPE_WITH_PRIVATE (CajaFileConflictDialog,
67 caja_file_conflict_dialog,
68 GTK_TYPE_DIALOG);
69
70 static void
file_icons_changed(CajaFile * file,CajaFileConflictDialog * fcd)71 file_icons_changed (CajaFile *file,
72 CajaFileConflictDialog *fcd)
73 {
74 cairo_surface_t *surface;
75
76 surface = caja_file_get_icon_surface (fcd->details->destination,
77 CAJA_ICON_SIZE_LARGE,
78 FALSE,
79 gtk_widget_get_scale_factor (fcd->details->dest_image),
80 CAJA_FILE_ICON_FLAGS_USE_THUMBNAILS);
81
82 gtk_image_set_from_surface (GTK_IMAGE (fcd->details->dest_image), surface);
83 cairo_surface_destroy (surface);
84
85 surface = caja_file_get_icon_surface (fcd->details->source,
86 CAJA_ICON_SIZE_LARGE,
87 FALSE,
88 gtk_widget_get_scale_factor (fcd->details->src_image),
89 CAJA_FILE_ICON_FLAGS_USE_THUMBNAILS);
90
91 gtk_image_set_from_surface (GTK_IMAGE (fcd->details->src_image), surface);
92 cairo_surface_destroy (surface);
93 }
94
95 static void
file_list_ready_cb(GList * files,gpointer user_data)96 file_list_ready_cb (GList *files,
97 gpointer user_data)
98 {
99 CajaFileConflictDialog *fcd = user_data;
100 CajaFile *src, *dest, *dest_dir;
101 time_t src_mtime, dest_mtime;
102 gboolean source_is_dir, dest_is_dir, should_show_type;
103 CajaFileConflictDialogPrivate *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 cairo_surface_t *surface;
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 = caja_file_get_mtime (src);
123 dest_mtime = caja_file_get_mtime (dest);
124
125 dest_name = caja_file_get_display_name (dest);
126 dest_dir_name = caja_file_get_display_name (dest_dir);
127
128 source_is_dir = caja_file_is_directory (src);
129 dest_is_dir = caja_file_is_directory (dest);
130
131 type = caja_file_get_mime_type (dest);
132 should_show_type = !caja_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 {
140 if (source_is_dir)
141 {
142 primary_text = g_strdup_printf
143 (_("Merge folder \"%s\"?"),
144 dest_name);
145
146 message_extra =
147 _("Merging will ask for confirmation before replacing any files in "
148 "the folder that conflict with the files being copied.");
149
150 if (src_mtime > dest_mtime)
151 {
152 message = g_strdup_printf (
153 _("An older folder with the same name already exists in \"%s\"."),
154 dest_dir_name);
155 }
156 else if (src_mtime < dest_mtime)
157 {
158 message = g_strdup_printf (
159 _("A newer folder with the same name already exists in \"%s\"."),
160 dest_dir_name);
161 }
162 else
163 {
164 message = g_strdup_printf (
165 _("Another folder with the same name already exists in \"%s\"."),
166 dest_dir_name);
167 }
168 }
169 else
170 {
171 message_extra =
172 _("Replacing it will remove all files in the folder.");
173 primary_text = g_strdup_printf
174 (_("Replace folder \"%s\"?"), dest_name);
175 message = g_strdup_printf
176 (_("A folder with the same name already exists in \"%s\"."),
177 dest_dir_name);
178 }
179 }
180 else
181 {
182 primary_text = g_strdup_printf
183 (_("Replace file \"%s\"?"), dest_name);
184
185 message_extra = _("Replacing it will overwrite its content.");
186
187 if (src_mtime > dest_mtime)
188 {
189 message = g_strdup_printf (
190 _("An older file with the same name already exists in \"%s\"."),
191 dest_dir_name);
192 }
193 else if (src_mtime < dest_mtime)
194 {
195 message = g_strdup_printf (
196 _("A newer file with the same name already exists in \"%s\"."),
197 dest_dir_name);
198 }
199 else
200 {
201 message = g_strdup_printf (
202 _("Another file with the same name already exists in \"%s\"."),
203 dest_dir_name);
204 }
205 }
206
207 secondary_text = g_strdup_printf ("%s\n%s", message, message_extra);
208 g_free (message);
209
210 label = gtk_label_new (primary_text);
211 gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
212 gtk_label_set_line_wrap_mode (GTK_LABEL (label), PANGO_WRAP_WORD_CHAR);
213 gtk_label_set_xalign (GTK_LABEL (label), 0.0);
214 gtk_box_pack_start (GTK_BOX (details->titles_vbox),
215 label, FALSE, FALSE, 0);
216 gtk_widget_show (label);
217
218 attr_list = pango_attr_list_new ();
219 pango_attr_list_insert (attr_list, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
220 pango_attr_list_insert (attr_list, pango_attr_scale_new (PANGO_SCALE_LARGE));
221 g_object_set (label,
222 "attributes", attr_list,
223 NULL);
224
225 pango_attr_list_unref (attr_list);
226 label = gtk_label_new (secondary_text);
227 gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
228 gtk_label_set_max_width_chars (GTK_LABEL (label), 60);
229 gtk_label_set_xalign (GTK_LABEL (label), 0.0);
230 gtk_box_pack_start (GTK_BOX (details->titles_vbox),
231 label, FALSE, FALSE, 0);
232 gtk_widget_show (label);
233 g_free (primary_text);
234 g_free (secondary_text);
235
236 /* Set up file icons */
237 surface = caja_file_get_icon_surface (dest,
238 CAJA_ICON_SIZE_LARGE,
239 TRUE,
240 gtk_widget_get_scale_factor (fcd->details->titles_vbox),
241 CAJA_FILE_ICON_FLAGS_USE_THUMBNAILS);
242 details->dest_image = gtk_image_new_from_surface (surface);
243 gtk_box_pack_start (GTK_BOX (details->first_hbox),
244 details->dest_image, FALSE, FALSE, 0);
245 gtk_widget_show (details->dest_image);
246 cairo_surface_destroy (surface);
247
248 surface = caja_file_get_icon_surface (src,
249 CAJA_ICON_SIZE_LARGE,
250 TRUE,
251 gtk_widget_get_scale_factor (fcd->details->titles_vbox),
252 CAJA_FILE_ICON_FLAGS_USE_THUMBNAILS);
253 details->src_image = gtk_image_new_from_surface (surface);
254 gtk_box_pack_start (GTK_BOX (details->second_hbox),
255 details->src_image, FALSE, FALSE, 0);
256 gtk_widget_show (details->src_image);
257 cairo_surface_destroy (surface);
258
259 /* Set up labels */
260 label = gtk_label_new (NULL);
261 date = caja_file_get_string_attribute (dest,
262 "date_modified");
263 size = caja_file_get_string_attribute (dest, "size");
264
265 if (should_show_type)
266 {
267 type = caja_file_get_string_attribute (dest, "type");
268 }
269
270 str = g_string_new (NULL);
271 if (dest_is_dir) {
272 g_string_append_printf (str, "<b>%s</b>\n", _("Original folder"));
273 g_string_append_printf (str, "%s %s\n", _("Items:"), size);
274 }
275 else {
276 g_string_append_printf (str, "<b>%s</b>\n", _("Original file"));
277 g_string_append_printf (str, "%s %s\n", _("Size:"), size);
278 }
279
280 if (should_show_type)
281 {
282 g_string_append_printf (str, "%s %s\n", _("Type:"), type);
283 }
284
285 g_string_append_printf (str, "%s %s", _("Last modified:"), date);
286
287 label_text = str->str;
288 gtk_label_set_markup (GTK_LABEL (label),
289 label_text);
290 gtk_box_pack_start (GTK_BOX (details->first_hbox),
291 label, FALSE, FALSE, 0);
292 gtk_widget_show (label);
293
294 g_free (size);
295 g_free (type);
296 g_free (date);
297 g_string_erase (str, 0, -1);
298
299 /* Second label */
300 label = gtk_label_new (NULL);
301 date = caja_file_get_string_attribute (src,
302 "date_modified");
303 size = caja_file_get_string_attribute (src, "size");
304
305 if (should_show_type)
306 {
307 type = caja_file_get_string_attribute (src, "type");
308 }
309
310 if (source_is_dir) {
311 g_string_append_printf (str, "<b>%s</b>\n", dest_is_dir ? _("Merge with") : _("Replace with"));
312 g_string_append_printf (str, "%s %s\n", _("Items:"), size);
313 }
314 else {
315 g_string_append_printf (str, "<b>%s</b>\n", _("Replace with"));
316 g_string_append_printf (str, "%s %s\n", _("Size:"), size);
317 }
318
319 if (should_show_type)
320 {
321 g_string_append_printf (str, "%s %s\n", _("Type:"), type);
322 }
323
324 g_string_append_printf (str, "%s %s", _("Last modified:"), date);
325 label_text = g_string_free (str, FALSE);
326
327 gtk_label_set_markup (GTK_LABEL (label),
328 label_text);
329 gtk_box_pack_start (GTK_BOX (details->second_hbox),
330 label, FALSE, FALSE, 0);
331 gtk_widget_show (label);
332
333 g_free (size);
334 g_free (date);
335 g_free (type);
336 g_free (label_text);
337
338 /* Populate the entry */
339 edit_name = caja_file_get_edit_name (dest);
340 details->conflict_name = edit_name;
341
342 gtk_entry_set_text (GTK_ENTRY (details->entry), edit_name);
343
344 if (source_is_dir && dest_is_dir)
345 {
346 gtk_button_set_label (GTK_BUTTON (details->replace_button),
347 _("Merge"));
348 }
349
350 /* If meld is installed, and source and destination arent binary
351 * files, show the diff button
352 */
353 gtk_widget_hide (details->diff_button);
354 if (!source_is_dir && !dest_is_dir)
355 {
356 gchar *meld_found = g_find_program_in_path ("meld");
357 if (meld_found) {
358 g_free (meld_found);
359 gboolean src_is_binary;
360 gboolean dest_is_binary;
361
362 src_is_binary = caja_file_is_binary (details->source);
363 dest_is_binary = caja_file_is_binary (details->destination);
364
365 if (!src_is_binary && !dest_is_binary)
366 gtk_widget_show (details->diff_button);
367 }
368 }
369
370 caja_file_monitor_add (src, fcd, CAJA_FILE_ATTRIBUTES_FOR_ICON);
371 caja_file_monitor_add (dest, fcd, CAJA_FILE_ATTRIBUTES_FOR_ICON);
372
373 details->src_handler_id = g_signal_connect (src, "changed",
374 G_CALLBACK (file_icons_changed), fcd);
375 details->dest_handler_id = g_signal_connect (dest, "changed",
376 G_CALLBACK (file_icons_changed), fcd);
377 }
378
379 static void
build_dialog_appearance(CajaFileConflictDialog * fcd)380 build_dialog_appearance (CajaFileConflictDialog *fcd)
381 {
382 GList *files = NULL;
383 CajaFileConflictDialogPrivate *details = fcd->details;
384
385 files = g_list_prepend (files, details->source);
386 files = g_list_prepend (files, details->destination);
387 files = g_list_prepend (files, details->dest_dir);
388
389 caja_file_list_call_when_ready (files,
390 CAJA_FILE_ATTRIBUTES_FOR_ICON,
391 &details->handle, file_list_ready_cb, fcd);
392 g_list_free (files);
393 }
394
395 static void
set_source_and_destination(GtkWidget * w,GFile * source,GFile * destination,GFile * dest_dir)396 set_source_and_destination (GtkWidget *w,
397 GFile *source,
398 GFile *destination,
399 GFile *dest_dir)
400 {
401 CajaFileConflictDialog *dialog;
402 CajaFileConflictDialogPrivate *details;
403
404 dialog = CAJA_FILE_CONFLICT_DIALOG (w);
405 details = dialog->details;
406
407 details->source = caja_file_get (source);
408 details->destination = caja_file_get (destination);
409 details->dest_dir = caja_file_get (dest_dir);
410
411 build_dialog_appearance (dialog);
412 }
413
414 static void
entry_text_changed_cb(GtkEditable * entry,CajaFileConflictDialog * dialog)415 entry_text_changed_cb (GtkEditable *entry,
416 CajaFileConflictDialog *dialog)
417 {
418 CajaFileConflictDialogPrivate *details;
419
420 details = dialog->details;
421
422 /* The rename button is visible only if there's text
423 * in the entry.
424 */
425 if (g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (entry)), "") != 0 &&
426 g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (entry)), details->conflict_name) != 0)
427 {
428 gtk_widget_hide (details->replace_button);
429 gtk_widget_show (details->rename_button);
430
431 gtk_widget_set_sensitive (details->checkbox, FALSE);
432
433 gtk_dialog_set_default_response (GTK_DIALOG (dialog),
434 CONFLICT_RESPONSE_RENAME);
435 }
436 else
437 {
438 gtk_widget_hide (details->rename_button);
439 gtk_widget_show (details->replace_button);
440
441 gtk_widget_set_sensitive (details->checkbox, TRUE);
442
443 gtk_dialog_set_default_response (GTK_DIALOG (dialog),
444 CONFLICT_RESPONSE_REPLACE);
445 }
446 }
447
448 static void
expander_activated_cb(GtkExpander * w,CajaFileConflictDialog * dialog)449 expander_activated_cb (GtkExpander *w,
450 CajaFileConflictDialog *dialog)
451 {
452 CajaFileConflictDialogPrivate *details;
453 int start_pos, end_pos;
454
455 details = dialog->details;
456
457 if (!gtk_expander_get_expanded (w))
458 {
459 if (g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (details->entry)),
460 details->conflict_name) == 0)
461 {
462 gtk_widget_grab_focus (details->entry);
463
464 eel_filename_get_rename_region (details->conflict_name,
465 &start_pos, &end_pos);
466 gtk_editable_select_region (GTK_EDITABLE (details->entry),
467 start_pos, end_pos);
468 }
469 }
470 }
471
472 static void
checkbox_toggled_cb(GtkToggleButton * t,CajaFileConflictDialog * dialog)473 checkbox_toggled_cb (GtkToggleButton *t,
474 CajaFileConflictDialog *dialog)
475 {
476 CajaFileConflictDialogPrivate *details;
477
478 details = dialog->details;
479
480 gtk_widget_set_sensitive (details->expander,
481 !gtk_toggle_button_get_active (t));
482 gtk_widget_set_sensitive (details->rename_button,
483 !gtk_toggle_button_get_active (t));
484
485 if (!gtk_toggle_button_get_active (t) &&
486 g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (details->entry)),
487 "") != 0 &&
488 g_strcmp0 (gtk_entry_get_text (GTK_ENTRY (details->entry)),
489 details->conflict_name) != 0)
490 {
491 gtk_widget_hide (details->replace_button);
492 gtk_widget_show (details->rename_button);
493 }
494 else
495 {
496 gtk_widget_hide (details->rename_button);
497 gtk_widget_show (details->replace_button);
498 }
499 }
500
501 static void
reset_button_clicked_cb(GtkButton * w,CajaFileConflictDialog * dialog)502 reset_button_clicked_cb (GtkButton *w,
503 CajaFileConflictDialog *dialog)
504 {
505 CajaFileConflictDialogPrivate *details;
506 int start_pos, end_pos;
507
508 details = dialog->details;
509
510 gtk_entry_set_text (GTK_ENTRY (details->entry),
511 details->conflict_name);
512 gtk_widget_grab_focus (details->entry);
513 eel_filename_get_rename_region (details->conflict_name,
514 &start_pos, &end_pos);
515 gtk_editable_select_region (GTK_EDITABLE (details->entry),
516 start_pos, end_pos);
517
518 }
519
520 static void
diff_button_clicked_cb(GtkButton * w,CajaFileConflictDialog * dialog)521 diff_button_clicked_cb (GtkButton *w,
522 CajaFileConflictDialog *dialog)
523 {
524 CajaFileConflictDialogPrivate *details;
525 details = dialog->details;
526
527 GError *error;
528 char *command;
529
530 command = g_find_program_in_path ("meld");
531 if (command)
532 {
533 char **argv;
534
535 argv = g_new (char *, 4);
536 argv[0] = command;
537 argv[1] = g_file_get_path (caja_file_get_location (details->source));
538 argv[2] = g_file_get_path (caja_file_get_location (details->destination));
539 argv[3] = NULL;
540
541 error = NULL;
542 if (!g_spawn_async_with_pipes (NULL,
543 argv,
544 NULL,
545 G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL,
546 NULL,
547 NULL /* user_data */,
548 NULL,
549 NULL, NULL, NULL,
550 &error))
551 {
552 g_warning ("Error opening meld to show differences: %s\n", error->message);
553 g_error_free (error);
554 }
555 g_strfreev (argv);
556 }
557 }
558
559 static void
caja_file_conflict_dialog_init(CajaFileConflictDialog * fcd)560 caja_file_conflict_dialog_init (CajaFileConflictDialog *fcd)
561 {
562 GtkWidget *hbox, *vbox, *vbox2;
563 GtkWidget *widget, *dialog_area;
564 CajaFileConflictDialogPrivate *details;
565 GtkDialog *dialog;
566
567 details = fcd->details = caja_file_conflict_dialog_get_instance_private (fcd);
568 dialog = GTK_DIALOG (fcd);
569
570 /* Setup the main hbox */
571 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
572 dialog_area = gtk_dialog_get_content_area (dialog);
573 gtk_box_pack_start (GTK_BOX (dialog_area), hbox, FALSE, FALSE, 0);
574 gtk_container_set_border_width (GTK_CONTAINER (hbox), 6);
575
576 /* Setup the dialog image */
577 widget = gtk_image_new_from_icon_name ("dialog-warning",
578 GTK_ICON_SIZE_DIALOG);
579 gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
580 gtk_widget_set_halign (widget, GTK_ALIGN_CENTER);
581 gtk_widget_set_valign (widget, GTK_ALIGN_START);
582
583 /* Setup the vbox containing the dialog body */
584 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
585 gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
586
587 /* Setup the vbox for the dialog labels */
588 widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
589 gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
590 details->titles_vbox = widget;
591
592 /* Setup the hboxes to pack file infos into */
593 vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
594 gtk_widget_set_halign (vbox2, GTK_ALIGN_START);
595 gtk_widget_set_valign (vbox2, GTK_ALIGN_START);
596 gtk_widget_set_margin_start (vbox2, 12);
597 gtk_box_pack_start (GTK_BOX (vbox), vbox2, FALSE, FALSE, 0);
598
599 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
600 gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, FALSE, 0);
601 details->first_hbox = hbox;
602
603 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
604 gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, FALSE, 0);
605 details->second_hbox = hbox;
606
607 /* Setup the expander for the rename action */
608 details->expander = gtk_expander_new_with_mnemonic (_("Select a new name for the _destination"));
609 gtk_box_pack_start (GTK_BOX (vbox2), details->expander, FALSE, FALSE, 0);
610 g_signal_connect (details->expander, "activate",
611 G_CALLBACK (expander_activated_cb), dialog);
612
613 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
614 gtk_container_add (GTK_CONTAINER (details->expander), hbox);
615
616 widget = gtk_entry_new ();
617 gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 6);
618 details->entry = widget;
619 g_signal_connect (widget, "changed",
620 G_CALLBACK (entry_text_changed_cb), dialog);
621
622 widget = gtk_button_new_with_label (_("Reset"));
623 gtk_button_set_image (GTK_BUTTON (widget),
624 gtk_image_new_from_icon_name ("edit-undo",
625 GTK_ICON_SIZE_MENU));
626 gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 6);
627 g_signal_connect (widget, "clicked",
628 G_CALLBACK (reset_button_clicked_cb), dialog);
629
630 gtk_widget_show_all (vbox2);
631
632 /* Setup the diff button for text files */
633 details->diff_button = gtk_button_new_with_label (_("Differences..."));
634 gtk_button_set_image (GTK_BUTTON (details->diff_button),
635 gtk_image_new_from_icon_name ("edit-find",
636 GTK_ICON_SIZE_MENU));
637 gtk_box_pack_start (GTK_BOX (vbox), details->diff_button, FALSE, FALSE, 6);
638 g_signal_connect (details->diff_button, "clicked",
639 G_CALLBACK (diff_button_clicked_cb), dialog);
640 gtk_widget_hide (details->diff_button);
641
642 /* Setup the checkbox to apply the action to all files */
643 widget = gtk_check_button_new_with_mnemonic (_("Apply this action to all files and folders"));
644
645 gtk_box_pack_start (GTK_BOX (vbox),
646 widget, FALSE, FALSE, 0);
647 details->checkbox = widget;
648 g_signal_connect (widget, "toggled",
649 G_CALLBACK (checkbox_toggled_cb), dialog);
650
651 /* Add buttons */
652 eel_dialog_add_button (dialog,
653 _("_Cancel"),
654 "process-stop",
655 GTK_RESPONSE_CANCEL);
656
657 gtk_dialog_add_button (dialog,
658 _("_Skip"),
659 CONFLICT_RESPONSE_SKIP);
660
661 details->rename_button =
662 gtk_dialog_add_button (dialog,
663 _("Re_name"),
664 CONFLICT_RESPONSE_RENAME);
665 gtk_widget_hide (details->rename_button);
666
667 details->replace_button =
668 gtk_dialog_add_button (dialog,
669 _("Replace"),
670 CONFLICT_RESPONSE_REPLACE);
671 gtk_widget_grab_focus (details->replace_button);
672
673 /* Setup HIG properties */
674 gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
675 gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (dialog)), 14);
676 gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
677
678 gtk_widget_show_all (dialog_area);
679 }
680
681 static void
do_finalize(GObject * self)682 do_finalize (GObject *self)
683 {
684 CajaFileConflictDialogPrivate *details =
685 CAJA_FILE_CONFLICT_DIALOG (self)->details;
686
687 g_free (details->conflict_name);
688
689 if (details->handle != NULL)
690 {
691 caja_file_list_cancel_call_when_ready (details->handle);
692 }
693
694 if (details->src_handler_id)
695 {
696 g_signal_handler_disconnect (details->source, details->src_handler_id);
697 caja_file_monitor_remove (details->source, self);
698 }
699
700 if (details->dest_handler_id)
701 {
702 g_signal_handler_disconnect (details->destination, details->dest_handler_id);
703 caja_file_monitor_remove (details->destination, self);
704 }
705
706 caja_file_unref (details->source);
707 caja_file_unref (details->destination);
708 caja_file_unref (details->dest_dir);
709
710 G_OBJECT_CLASS (caja_file_conflict_dialog_parent_class)->finalize (self);
711 }
712
713 static void
caja_file_conflict_dialog_class_init(CajaFileConflictDialogClass * klass)714 caja_file_conflict_dialog_class_init (CajaFileConflictDialogClass *klass)
715 {
716 G_OBJECT_CLASS (klass)->finalize = do_finalize;
717 }
718
719 char *
caja_file_conflict_dialog_get_new_name(CajaFileConflictDialog * dialog)720 caja_file_conflict_dialog_get_new_name (CajaFileConflictDialog *dialog)
721 {
722 return g_strdup (gtk_entry_get_text
723 (GTK_ENTRY (dialog->details->entry)));
724 }
725
726 gboolean
caja_file_conflict_dialog_get_apply_to_all(CajaFileConflictDialog * dialog)727 caja_file_conflict_dialog_get_apply_to_all (CajaFileConflictDialog *dialog)
728 {
729 return gtk_toggle_button_get_active
730 (GTK_TOGGLE_BUTTON (dialog->details->checkbox));
731 }
732
733 GtkWidget *
caja_file_conflict_dialog_new(GtkWindow * parent,GFile * source,GFile * destination,GFile * dest_dir)734 caja_file_conflict_dialog_new (GtkWindow *parent,
735 GFile *source,
736 GFile *destination,
737 GFile *dest_dir)
738 {
739 GtkWidget *dialog;
740 CajaFile *src, *dest;
741 gboolean source_is_dir, dest_is_dir;
742
743 src = caja_file_get (source);
744 dest = caja_file_get (destination);
745
746 source_is_dir = caja_file_is_directory (src);
747 dest_is_dir = caja_file_is_directory (dest);
748
749 if (source_is_dir) {
750 dialog = GTK_WIDGET (g_object_new (CAJA_TYPE_FILE_CONFLICT_DIALOG,
751 "title", dest_is_dir ? _("Merge Folder") : _("File and Folder conflict"),
752 NULL));
753 }
754 else {
755 dialog = GTK_WIDGET (g_object_new (CAJA_TYPE_FILE_CONFLICT_DIALOG,
756 "title", dest_is_dir ? _("File and Folder conflict") : _("File conflict"),
757 NULL));
758 }
759
760 set_source_and_destination (dialog,
761 source,
762 destination,
763 dest_dir);
764 gtk_window_set_transient_for (GTK_WINDOW (dialog),
765 parent);
766 return dialog;
767 }
768