1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
10 #include "fileopctx.h"
13 #include "../vfs/vfs.h"
25 /* This structure describes the UI and internal data required by a file
29 /* The progress window */
32 /* Set to FALSE in file_op_context_create_ui, set on the cancel_cb if
33 * user click on Cancel.
37 /* Source file label */
38 GtkWidget
*op_source_label
;
40 /* Target file label */
41 GtkWidget
*op_target_label
;
43 /* File number label */
44 GtkObject
*count_label
;
46 /* Current file label */
47 GtkWidget
*file_label
;
49 /* Bytes progress bar */
52 /* Copy status in query replace dialog */
54 int minor_copy_status
;
56 /* Overwrite toggle */
60 static char *gdialog_to_string
= N_("To: ");
61 static char *gdialog_from_string
= N_("Copying from: ");
62 static char *gdialog_deleting_string
= N_("Deleting file: ");
64 #define GDIALOG_PROGRESS_WIDTH 350
66 /* Callbacks go here... */
68 fmd_check_box_callback (GtkWidget
*widget
, gpointer data
)
71 *((gint
*)data
) = GTK_TOGGLE_BUTTON (widget
)->active
;
75 trim_file_name (FileOpContextUI
*ui
, gchar
*path
, gint length
, gint cur_length
)
77 static gint dotdotdot
= 0;
78 gchar
*path_copy
= NULL
;
82 dotdotdot
= gdk_string_width (ui
->op_source_label
->style
->font
, "...");
83 /* Cut the font length of path to length. */
86 len
= (gint
) ((1.0 - (gfloat
) length
/ (gfloat
) cur_length
) * strlen (path
));
88 /* we guess a starting point */
89 if (gdk_string_width (ui
->op_source_label
->style
->font
, path
+ len
) < length
) {
90 while (gdk_string_width (ui
->op_source_label
->style
->font
, path
+ len
) < length
)
94 while (gdk_string_width (ui
->op_source_label
->style
->font
, path
+ len
) > length
)
98 path_copy
= g_strdup_printf ("...%s", path
+ len
);
103 file_progress_show_source (FileOpContext
*ctx
, char *path
)
105 static gint from_width
= 0;
108 gchar
*path_copy
= NULL
;
110 g_return_val_if_fail (ctx
!= NULL
, FILE_CONT
);
112 /* ctx->ui might be NULL for background processes */
118 g_return_val_if_fail (ui
->op_source_label
!= NULL
, FILE_CONT
);
124 gtk_label_set_text (GTK_LABEL (ui
->op_source_label
), "");
129 from_width
= gdk_string_width (ui
->op_source_label
->style
->font
,
130 _(gdialog_from_string
));
132 path_width
= gdk_string_width (ui
->op_source_label
->style
->font
, path
);
133 if (from_width
+ path_width
< GDIALOG_PROGRESS_WIDTH
)
134 gtk_label_set_text (GTK_LABEL (ui
->op_source_label
), path
);
136 path_copy
= trim_file_name (ui
, path
, GDIALOG_PROGRESS_WIDTH
- from_width
,
139 gtk_label_set_text (GTK_LABEL (ui
->op_source_label
), path_copy
);
147 file_progress_show_target (FileOpContext
*ctx
, char *path
)
149 static gint to_width
= 0;
152 gchar
*path_copy
= NULL
;
154 g_return_val_if_fail (ctx
!= NULL
, FILE_CONT
);
155 /* ctx->ui might be NULL for background processes */
161 g_return_val_if_fail (ui
->op_target_label
!= NULL
, FILE_CONT
);
167 gtk_label_set_text (GTK_LABEL (ui
->op_target_label
), "");
172 to_width
= gdk_string_width (ui
->op_target_label
->style
->font
,
173 _(gdialog_to_string
));
174 path_width
= gdk_string_width (ui
->op_target_label
->style
->font
, path
);
175 if (to_width
+ path_width
< GDIALOG_PROGRESS_WIDTH
)
176 gtk_label_set_text (GTK_LABEL (ui
->op_target_label
), path
);
178 path_copy
= trim_file_name (ui
, path
, GDIALOG_PROGRESS_WIDTH
- to_width
, path_width
);
179 gtk_label_set_text (GTK_LABEL (ui
->op_target_label
), path_copy
);
187 file_progress_show_deleting (FileOpContext
*ctx
, char *path
)
189 static gint deleting_width
= 0;
192 gchar
*path_copy
= NULL
;
194 g_return_val_if_fail (ctx
!= NULL
, FILE_CONT
);
196 /* ctx->ui might be NULL for background processes */
206 gtk_label_set_text (GTK_LABEL (ui
->op_source_label
), "");
210 if (!deleting_width
){
211 deleting_width
= gdk_string_width (ui
->op_source_label
->style
->font
,
212 _(gdialog_deleting_string
));
214 path_width
= gdk_string_width (ui
->op_source_label
->style
->font
, path
);
215 if (deleting_width
+ path_width
< GDIALOG_PROGRESS_WIDTH
)
216 gtk_label_set_text (GTK_LABEL (ui
->op_source_label
), path
);
218 path_copy
= trim_file_name (ui
, path
, GDIALOG_PROGRESS_WIDTH
- deleting_width
,
221 gtk_label_set_text (GTK_LABEL (ui
->op_source_label
), path_copy
);
228 file_progress_show (FileOpContext
*ctx
, long done
, long total
)
230 static gchar count
[20];
234 g_return_val_if_fail (ctx
!= NULL
, FILE_CONT
);
236 /* ctx->ui might be NULL for background processes */
246 perc
= (double) done
/ (double) total
;
247 snprintf (count
, 9, "%3d%% ", (gint
) (100.0 * perc
));
248 gtk_label_set_text (GTK_LABEL (ui
->file_label
), count
);
250 while (gtk_events_pending ())
251 gtk_main_iteration ();
256 file_progress_show_count (FileOpContext
*ctx
, long done
, long total
)
258 static gchar count
[100];
261 g_return_val_if_fail (ctx
!= NULL
, FILE_CONT
);
263 /* ctx->ui might be NULL for background processes */
272 snprintf (count
, 100, "%ld/%ld ", done
, total
);
273 gtk_label_set_text (GTK_LABEL (ui
->count_label
), count
);
274 while (gtk_events_pending ())
275 gtk_main_iteration ();
280 file_progress_show_bytes (FileOpContext
*ctx
, double done
, double total
)
285 g_return_val_if_fail (ctx
!= NULL
, FILE_CONT
);
287 /* ctx->ui might be NULL for background processes */
301 gtk_progress_bar_update (GTK_PROGRESS_BAR (ui
->byte_prog
), CLAMP (perc
, 0.0, 1.0));
303 while (gtk_events_pending ())
304 gtk_main_iteration ();
309 option_menu_policy_callback (GtkWidget
*item
, gpointer data
)
315 status
= GPOINTER_TO_INT (gtk_object_get_user_data (GTK_OBJECT (item
)));
317 ui
->minor_copy_status
= status
;
318 ui
->copy_status
= status
;
319 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ui
->op_radio
), TRUE
);
323 policy_callback (GtkWidget
*button
, gpointer data
)
329 status
= GPOINTER_TO_INT (gtk_object_get_user_data (GTK_OBJECT (button
)));
331 if (GTK_TOGGLE_BUTTON (button
)->active
) {
332 if (status
== REPLACE_OPTION_MENU
) {
333 ui
->copy_status
= ui
->minor_copy_status
;
335 ui
->copy_status
= status
;
340 file_progress_query_replace_policy (FileOpContext
*ctx
, gboolean dialog_needed
)
351 GSList
*group
= NULL
;
354 GtkWidget
*menu_item
;
356 g_return_val_if_fail (ctx
!= NULL
, FILE_CONT
);
358 /* ctx->ui might be NULL for background processes */
367 ui
->copy_status
= REPLACE_PROMPT
;
368 if (dialog_needed
== FALSE
)
370 ui
->minor_copy_status
= REPLACE_ALWAYS
;
371 qrp_dlg
= gnome_dialog_new (_("Files Exist"),
372 GNOME_STOCK_BUTTON_OK
,
373 GNOME_STOCK_BUTTON_CANCEL
,
375 gtk_window_set_position (GTK_WINDOW (qrp_dlg
), GTK_WIN_POS_MOUSE
);
377 hbox
= gtk_hbox_new (FALSE
, GNOME_PAD_SMALL
);
378 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (qrp_dlg
)->vbox
), hbox
, FALSE
, FALSE
, 0);
380 icon
= gnome_stock_pixmap_widget (hbox
, GNOME_STOCK_PIXMAP_HELP
);
381 gtk_box_pack_start (GTK_BOX (hbox
), icon
, FALSE
, FALSE
, 0);
383 vbox
= gtk_vbox_new (FALSE
, GNOME_PAD_SMALL
);
384 gtk_box_pack_start (GTK_BOX (hbox
), vbox
, FALSE
, FALSE
, GNOME_PAD_SMALL
);
386 label
= gtk_label_new (_("Some of the files you are trying to copy already "
387 "exist in the destination folder. Please select "
388 "the action to be performed."));
389 gtk_misc_set_alignment (GTK_MISC (label
), 0.0, 0.5);
390 gtk_label_set_justify (GTK_LABEL (label
), GTK_JUSTIFY_LEFT
);
391 gtk_label_set_line_wrap (GTK_LABEL (label
), TRUE
);
393 gtk_box_pack_start (GTK_BOX (vbox
), label
, FALSE
, FALSE
, 0);
394 gtk_box_pack_start (GTK_BOX (vbox
), gtk_hseparator_new (), FALSE
, FALSE
, 0);
396 vbox2
= gtk_vbox_new (TRUE
, 0);
397 gtk_box_pack_start (GTK_BOX (vbox
), vbox2
, FALSE
, FALSE
, 0);
399 radio
= gtk_radio_button_new_with_label (group
, _("Prompt me before overwriting any file."));
400 gtk_object_set_user_data (GTK_OBJECT (radio
), GINT_TO_POINTER (REPLACE_PROMPT
));
401 gtk_signal_connect (GTK_OBJECT (radio
), "toggled",
402 GTK_SIGNAL_FUNC (policy_callback
), ui
);
403 gtk_box_pack_start (GTK_BOX (vbox2
), radio
, FALSE
, FALSE
, 0);
404 group
= gtk_radio_button_group (GTK_RADIO_BUTTON (radio
));
406 radio
= gtk_radio_button_new_with_label (group
, _("Don't overwrite any files."));
407 gtk_object_set_user_data (GTK_OBJECT (radio
), GINT_TO_POINTER (REPLACE_NEVER
));
408 gtk_signal_connect (GTK_OBJECT (radio
), "toggled",
409 GTK_SIGNAL_FUNC (policy_callback
), ui
);
410 gtk_box_pack_start (GTK_BOX (vbox2
), radio
, FALSE
, FALSE
, 0);
411 group
= gtk_radio_button_group (GTK_RADIO_BUTTON (radio
));
413 ui
->op_radio
= gtk_radio_button_new (group
);
414 gtk_object_set_user_data (GTK_OBJECT (ui
->op_radio
), GINT_TO_POINTER (REPLACE_OPTION_MENU
));
415 gtk_signal_connect (GTK_OBJECT (ui
->op_radio
), "toggled",
416 GTK_SIGNAL_FUNC (policy_callback
), ui
);
417 gtk_box_pack_start (GTK_BOX (vbox2
), ui
->op_radio
, FALSE
, FALSE
, 0);
419 hrbox
= gtk_hbox_new (FALSE
, GNOME_PAD_SMALL
);
420 gtk_container_add (GTK_CONTAINER (ui
->op_radio
), hrbox
);
422 gtk_box_pack_start (GTK_BOX (hrbox
), gtk_label_new (_("Overwrite:")), FALSE
, FALSE
, 0);
424 /* we set up the option menu. */
425 omenu
= gtk_option_menu_new ();
426 gtk_box_pack_start (GTK_BOX (hrbox
), omenu
, FALSE
, FALSE
, 0);
427 menu
= gtk_menu_new ();
429 menu_item
= gtk_menu_item_new_with_label ( _("Older files."));
430 gtk_menu_append (GTK_MENU (menu
), menu_item
);
431 gtk_object_set_user_data (GTK_OBJECT (menu_item
), GINT_TO_POINTER (REPLACE_UPDATE
));
432 gtk_signal_connect (GTK_OBJECT (menu_item
), "activate",
433 GTK_SIGNAL_FUNC (option_menu_policy_callback
), ui
);
435 menu_item
= gtk_menu_item_new_with_label ( _("Files only if size differs."));
436 gtk_menu_append (GTK_MENU (menu
), menu_item
);
437 gtk_object_set_user_data (GTK_OBJECT (menu_item
), GINT_TO_POINTER (REPLACE_SIZE
));
438 gtk_signal_connect (GTK_OBJECT (menu_item
), "activate",
439 GTK_SIGNAL_FUNC (option_menu_policy_callback
), ui
);
441 menu_item
= gtk_menu_item_new_with_label ( _("All files."));
442 gtk_menu_append (GTK_MENU (menu
), menu_item
);
443 gtk_object_set_user_data (GTK_OBJECT (menu_item
), GINT_TO_POINTER (REPLACE_ALWAYS
));
444 gtk_signal_connect (GTK_OBJECT (menu_item
), "activate",
445 GTK_SIGNAL_FUNC (option_menu_policy_callback
), ui
);
447 gtk_widget_show_all (menu
);
448 gtk_option_menu_set_menu (GTK_OPTION_MENU (omenu
), menu
);
450 gtk_widget_show_all (GTK_WIDGET (GNOME_DIALOG (qrp_dlg
)->vbox
));
451 switch (gnome_dialog_run_and_close (GNOME_DIALOG (qrp_dlg
))) {
456 ui
->copy_status
= REPLACE_ABORT
;
463 file_progress_real_query_replace (FileOpContext
*ctx
, enum OperationMode mode
, char *destname
,
464 struct stat
*_s_stat
, struct stat
*_d_stat
)
471 g_return_val_if_fail (ctx
!= NULL
, FILE_CONT
);
472 g_return_val_if_fail (ctx
->ui
!= NULL
, FILE_CONT
);
479 /* so what's the situation? Do we prompt or don't we prompt. */
480 if (ui
->copy_status
== REPLACE_PROMPT
){
481 qr_dlg
= gnome_dialog_new (_("File Exists"),
482 GNOME_STOCK_BUTTON_YES
,
483 GNOME_STOCK_BUTTON_NO
,
484 GNOME_STOCK_BUTTON_CANCEL
, NULL
);
486 gtk_window_set_position (GTK_WINDOW (qr_dlg
), GTK_WIN_POS_MOUSE
);
487 snprintf (msg
, sizeof (msg
)-1, _("The target file already exists: %s"), destname
);
488 label
= gtk_label_new (msg
);
489 gtk_label_set_justify (GTK_LABEL (label
), GTK_JUSTIFY_LEFT
);
490 gtk_misc_set_alignment (GTK_MISC (label
), 0.0, 0.5);
491 gtk_label_set_line_wrap (GTK_LABEL (label
), TRUE
);
492 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (qr_dlg
)->vbox
),
493 label
, FALSE
, FALSE
, 0);
494 label
= gtk_label_new (_("Replace it?"));
495 gtk_label_set_justify (GTK_LABEL (label
), GTK_JUSTIFY_LEFT
);
496 gtk_misc_set_alignment (GTK_MISC (label
), 0.0, 0.5);
497 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (qr_dlg
)->vbox
),
498 label
, FALSE
, FALSE
, 0);
499 gtk_widget_show_all (GNOME_DIALOG (qr_dlg
)->vbox
);
500 switch (gnome_dialog_run_and_close (GNOME_DIALOG (qr_dlg
))) {
510 switch (ui
->copy_status
){
512 if (_s_stat
->st_mtime
> _d_stat
->st_mtime
)
517 if (_s_stat
->st_size
== _d_stat
->st_size
)
532 file_progress_set_stalled_label (FileOpContext
*ctx
, char *stalled_msg
)
534 g_return_if_fail (ctx
!= NULL
);
539 if (!stalled_msg
|| !*stalled_msg
)
542 g_warning ("FIXME: file_progress_set_stalled_label!\nmsg\t%s\n",stalled_msg
);
546 file_mask_dialog (FileOpContext
*ctx
, FileOperation operation
, char *text
, char *def_text
,
547 int only_one
, int *do_background
)
552 GtkWidget
*vbox
, *label
;
556 int source_easy_patterns
= easy_patterns
;
557 char *source_mask
, *orig_mask
, *dest_dir
;
562 g_return_val_if_fail (ctx
!= NULL
, NULL
);
564 ctx
->stable_symlinks
= 0;
567 if (operation
== OP_COPY
)
568 fmd_win
= gnome_dialog_new (_("Copy"), GNOME_STOCK_BUTTON_OK
,
569 GNOME_STOCK_BUTTON_CANCEL
, NULL
);
570 else if (operation
== OP_MOVE
)
571 fmd_win
= gnome_dialog_new (_("Move"), GNOME_STOCK_BUTTON_OK
,
572 GNOME_STOCK_BUTTON_CANCEL
, NULL
);
574 gtk_window_set_position (GTK_WINDOW (fmd_win
), GTK_WIN_POS_MOUSE
);
576 notebook
= gtk_notebook_new ();
577 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (fmd_win
)->vbox
),
578 notebook
, FALSE
, FALSE
, 0);
580 hbox
= gtk_hbox_new (FALSE
, GNOME_PAD
);
581 gtk_notebook_append_page (GTK_NOTEBOOK (notebook
),
583 gtk_label_new (_("Destination")));
585 /* FIXME: I want a bigger, badder, better Icon here... */
586 icon
= gnome_stock_pixmap_widget (hbox
, GNOME_STOCK_PIXMAP_HELP
);
587 gtk_box_pack_start (GTK_BOX (hbox
), icon
, FALSE
, FALSE
, 0);
589 vbox
= gtk_vbox_new (FALSE
, GNOME_PAD
);
590 gtk_box_pack_start (GTK_BOX (hbox
), vbox
, TRUE
, TRUE
, 0);
591 gtk_container_set_border_width (GTK_CONTAINER (vbox
), GNOME_PAD
);
593 label
= gtk_label_new (text
);
594 gtk_misc_set_alignment (GTK_MISC (label
), 0.0, 0.5);
595 gtk_box_pack_start (GTK_BOX (vbox
), label
, FALSE
, FALSE
, 0);
597 fentry
= gnome_file_entry_new ("gmc-copy-file", _("Find Destination Folder"));
598 gnome_file_entry_set_directory (GNOME_FILE_ENTRY (fentry
), TRUE
);
599 gtk_entry_set_text (GTK_ENTRY (gnome_file_entry_gtk_entry (GNOME_FILE_ENTRY (fentry
))),
601 gnome_file_entry_set_default_path (GNOME_FILE_ENTRY (fentry
), def_text
);
602 gnome_file_entry_set_modal (GNOME_FILE_ENTRY (fentry
), TRUE
);
603 gtk_box_pack_start (GTK_BOX (vbox
), fentry
, FALSE
, FALSE
, 0);
605 /* Background operations are completely hosed, so we olympically disable
606 * them. How's that for foolproof bugfixing.
609 *do_background
= FALSE
;
611 cbox
= gtk_check_button_new_with_label (_("Copy as a background process"));
612 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cbox
), *do_background
);
613 gtk_signal_connect (GTK_OBJECT (cbox
), "toggled",
614 (GtkSignalFunc
) fmd_check_box_callback
, do_background
);
616 gnome_widget_add_help (cbox
, "Selecting this will run the copying in the background. "
617 "This is useful for transfers over networks that might take a long "
618 "time to complete.");
620 gtk_box_pack_end (GTK_BOX (vbox
), cbox
, FALSE
, FALSE
, 0);
621 gtk_box_pack_end (GTK_BOX (vbox
), gtk_hseparator_new (), FALSE
, FALSE
, 0);
624 /* Advanced Options */
625 hbox
= gtk_hbox_new (FALSE
, GNOME_PAD_SMALL
);
626 vbox
= gtk_vbox_new (FALSE
, GNOME_PAD_SMALL
);
627 gtk_notebook_append_page (GTK_NOTEBOOK (notebook
),
629 gtk_label_new (_("Advanced Options")));
630 gtk_container_set_border_width (GTK_CONTAINER (hbox
), GNOME_PAD
);
631 gtk_box_pack_start (GTK_BOX (hbox
), vbox
, TRUE
, TRUE
, 0);
633 cbox
= gtk_check_button_new_with_label (_("Preserve symlinks"));
634 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cbox
), ctx
->stable_symlinks
);
635 gtk_signal_connect (GTK_OBJECT (cbox
), "toggled",
636 (GtkSignalFunc
) fmd_check_box_callback
, &ctx
->stable_symlinks
);
638 gnome_widget_add_help (cbox
, "FIXME: Add something here Miguel");
640 gtk_box_pack_start (GTK_BOX (vbox
), cbox
, FALSE
, FALSE
, 0);
642 if (operation
== OP_COPY
) {
643 cbox
= gtk_check_button_new_with_label (_("Follow links."));
644 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cbox
), ctx
->follow_links
);
645 gtk_signal_connect (GTK_OBJECT (cbox
), "toggled",
646 (GtkSignalFunc
) fmd_check_box_callback
, &ctx
->follow_links
);
648 gnome_widget_add_help (cbox
,
649 _("Selecting this will copy the files that symlinks point "
650 "to instead of just copying the link."));
652 gtk_box_pack_start (GTK_BOX (vbox
), cbox
, FALSE
, FALSE
, 0);
654 cbox
= gtk_check_button_new_with_label (_("Preserve file attributes."));
655 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cbox
), ctx
->op_preserve
);
656 gtk_signal_connect (GTK_OBJECT (cbox
), "toggled",
657 (GtkSignalFunc
) fmd_check_box_callback
, &ctx
->op_preserve
);
659 gnome_widget_add_help (cbox
,
660 _("Preserves the permissions and the UID/GID if possible"));
662 gtk_box_pack_start (GTK_BOX (vbox
), cbox
, FALSE
, FALSE
, 0);
664 vbox
= gtk_vbox_new (FALSE
, GNOME_PAD_SMALL
);
665 gtk_box_pack_start (GTK_BOX (hbox
), vbox
, TRUE
, TRUE
, 0);
666 cbox
= gtk_check_button_new_with_label (_("Recursively copy subdirectories."));
667 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cbox
), ctx
->dive_into_subdirs
);
668 gtk_signal_connect (GTK_OBJECT (cbox
), "toggled",
669 (GtkSignalFunc
) fmd_check_box_callback
,
670 &ctx
->dive_into_subdirs
);
672 gnome_widget_add_help (cbox
,
673 _("If set, this will copy the directories recursively"));
675 gtk_box_pack_start (GTK_BOX (vbox
), cbox
, FALSE
, FALSE
, 0);
678 gtk_widget_show_all (GNOME_DIALOG (fmd_win
)->vbox
);
679 gnome_dialog_set_close (GNOME_DIALOG (fmd_win
), TRUE
);
680 gnome_dialog_close_hides (GNOME_DIALOG (fmd_win
), TRUE
);
682 /* Off to the races!!! */
683 run
= gnome_dialog_run (GNOME_DIALOG (fmd_win
));
685 if (run
== 1 || run
== -1) {
686 gtk_widget_destroy (fmd_win
);
690 dest_dir
= gnome_file_entry_get_full_path (GNOME_FILE_ENTRY (fentry
), FALSE
);
691 gtk_widget_destroy (fmd_win
);
694 if (!dest_dir
|| !*dest_dir
)
697 if (ctx
->follow_links
&& operation
!= OP_MOVE
)
698 ctx
->stat_func
= mc_stat
;
700 ctx
->stat_func
= mc_lstat
;
702 if (ctx
->op_preserve
|| operation
== OP_MOVE
){
704 ctx
->umask_kill
= 0777777;
705 ctx
->preserve_uidgid
= (geteuid () == 0) ? 1 : 0;
708 ctx
->preserve
= ctx
->preserve_uidgid
= 0;
711 ctx
->umask_kill
= i
^ 0777777;
713 source_mask
= g_strdup ("*");
714 orig_mask
= source_mask
;
715 if (!dest_dir
|| !*dest_dir
){
717 g_free (source_mask
);
729 if (source_easy_patterns
) {
730 source_easy_patterns
= easy_patterns
;
732 source_mask
= convert_pattern (source_mask
, match_file
, 1);
733 easy_patterns
= source_easy_patterns
;
734 error
= re_compile_pattern (source_mask
, strlen (source_mask
), &ctx
->rx
);
735 g_free (source_mask
);
737 error
= re_compile_pattern (source_mask
, strlen (source_mask
), &ctx
->rx
);
740 g_warning ("%s\n",error
);
744 ctx
->dest_mask
= strrchr (dest_dir
, PATH_SEP
);
745 if (ctx
->dest_mask
== NULL
)
746 ctx
->dest_mask
= dest_dir
;
749 orig_mask
= ctx
->dest_mask
;
751 || (!ctx
->dive_into_subdirs
&& !is_wildcarded (ctx
->dest_mask
)
752 && (!only_one
|| (!mc_stat (dest_dir
, &buf
)
753 && S_ISDIR (buf
.st_mode
))))
754 || (ctx
->dive_into_subdirs
&& ((!only_one
&& !is_wildcarded (ctx
->dest_mask
))
755 || (only_one
&& !mc_stat (dest_dir
, &buf
)
756 && S_ISDIR (buf
.st_mode
)))))
757 ctx
->dest_mask
= g_strdup ("*");
759 ctx
->dest_mask
= g_strdup (ctx
->dest_mask
);
764 dest_dir
= g_strdup ("./");
770 file_delete_query_recursive (FileOpContext
*ctx
, enum OperationMode mode
, gchar
*s
)
773 GtkWidget
*togglebutton
;
779 if (ctx
->recursive_result
< RECURSIVE_ALWAYS
) {
780 msg
= g_strdup_printf (_("%s\n\nDirectory not empty. Delete it recursively?"),
782 dialog
= gnome_message_box_new (msg
,
783 GNOME_MESSAGE_BOX_QUESTION
,
784 GNOME_STOCK_BUTTON_YES
,
785 GNOME_STOCK_BUTTON_NO
,
786 GNOME_STOCK_BUTTON_CANCEL
,
790 title
= g_strconcat (_(" Delete: "), name_trunc (s
, 30), " ", NULL
);
791 gtk_window_set_title (GTK_WINDOW (dialog
), title
);
794 togglebutton
= gtk_check_button_new_with_label (_("Do the same for the rest"));
795 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog
)->vbox
),
796 togglebutton
, FALSE
, FALSE
, 0);
797 gtk_widget_show_all (GNOME_DIALOG (dialog
)->vbox
);
799 gnome_dialog_close_hides (GNOME_DIALOG (dialog
), TRUE
);
801 button
= gnome_dialog_run (GNOME_DIALOG (dialog
));
802 rest_same
= GTK_TOGGLE_BUTTON (togglebutton
)->active
;
804 gtk_widget_destroy (dialog
);
808 ctx
->recursive_result
= rest_same
? RECURSIVE_ALWAYS
: RECURSIVE_YES
;
811 ctx
->recursive_result
= rest_same
? RECURSIVE_NEVER
: RECURSIVE_NO
;
814 ctx
->recursive_result
= RECURSIVE_ABORT
;
819 if (ctx
->recursive_result
!= RECURSIVE_ABORT
)
823 switch (ctx
->recursive_result
){
825 case RECURSIVE_ALWAYS
:
829 case RECURSIVE_NEVER
:
832 case RECURSIVE_ABORT
:
840 cancel_cb (GtkWidget
*widget
, gpointer data
)
848 /* Handler for the close signal from the GnomeDialog in the file operation
849 * context UI. We mark the operation as "aborted" and ask GnomeDialog not to
850 * close the window for us.
853 close_cb (GtkWidget
*widget
, gpointer data
)
863 file_op_context_create_ui (FileOpContext
*ctx
, FileOperation op
, int with_eta
)
866 GtkWidget
*alignment
;
869 g_return_if_fail (ctx
!= NULL
);
870 g_return_if_fail (ctx
->ui
== NULL
);
872 ui
= g_new0 (FileOpContextUI
, 1);
877 ui
->op_win
= gnome_dialog_new (_("Move Progress"), GNOME_STOCK_BUTTON_CANCEL
, NULL
);
880 ui
->op_win
= gnome_dialog_new (_("Copy Progress"), GNOME_STOCK_BUTTON_CANCEL
, NULL
);
883 ui
->op_win
= gnome_dialog_new (_("Delete Progress"), GNOME_STOCK_BUTTON_CANCEL
, NULL
);
886 gtk_window_set_position (GTK_WINDOW (ui
->op_win
), GTK_WIN_POS_MOUSE
);
888 gnome_dialog_button_connect (GNOME_DIALOG (ui
->op_win
), 0,
889 GTK_SIGNAL_FUNC (cancel_cb
),
892 gtk_signal_connect (GTK_OBJECT (ui
->op_win
), "close",
893 GTK_SIGNAL_FUNC (close_cb
),
896 if (op
!= OP_DELETE
) {
897 alignment
= gtk_alignment_new (0.0, 0.5, 0, 0);
898 hbox
= gtk_hbox_new (FALSE
, 0);
899 gtk_container_add (GTK_CONTAINER (alignment
), hbox
);
900 gtk_box_pack_start (GTK_BOX (hbox
), gtk_label_new (_(gdialog_from_string
)),
902 ui
->op_source_label
= gtk_label_new ("");
904 gtk_box_pack_start (GTK_BOX (hbox
), ui
->op_source_label
, FALSE
, FALSE
, 0);
905 gtk_box_set_spacing (GTK_BOX (GNOME_DIALOG (ui
->op_win
)->vbox
), GNOME_PAD_SMALL
);
906 gtk_container_set_border_width (GTK_CONTAINER (GNOME_DIALOG (ui
->op_win
)->vbox
),
908 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (ui
->op_win
)->vbox
),
909 alignment
, FALSE
, FALSE
, 0);
911 alignment
= gtk_alignment_new (0.0, 0.5, 0, 0);
912 hbox
= gtk_hbox_new (FALSE
, 0);
913 gtk_container_add (GTK_CONTAINER (alignment
), hbox
);
914 gtk_box_pack_start (GTK_BOX (hbox
), gtk_label_new (_(gdialog_to_string
)),
916 ui
->op_target_label
= gtk_label_new ("");
917 gtk_box_pack_start (GTK_BOX (hbox
), ui
->op_target_label
, FALSE
, FALSE
, 0);
918 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (ui
->op_win
)->vbox
),
919 alignment
, FALSE
, FALSE
, 0);
922 alignment
= gtk_alignment_new (0.0, 0.5, 0, 0);
923 hbox
= gtk_hbox_new (FALSE
, 0);
924 gtk_container_add (GTK_CONTAINER (alignment
), hbox
);
925 gtk_box_pack_start (GTK_BOX (hbox
), gtk_label_new (_(gdialog_deleting_string
)),
927 ui
->op_source_label
= gtk_label_new ("");
929 gtk_box_pack_start (GTK_BOX (hbox
), ui
->op_source_label
, FALSE
, FALSE
, 0);
930 gtk_box_set_spacing (GTK_BOX (GNOME_DIALOG (ui
->op_win
)->vbox
), GNOME_PAD_SMALL
);
931 gtk_container_set_border_width (GTK_CONTAINER (GNOME_DIALOG (ui
->op_win
)->vbox
),
933 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (ui
->op_win
)->vbox
),
934 alignment
, FALSE
, FALSE
, 0);
937 alignment
= gtk_alignment_new (0.0, 0.5, 0, 0);
938 hbox
= gtk_hbox_new (FALSE
, 0);
939 gtk_box_pack_start (GTK_BOX (hbox
), gtk_label_new (_("File ")), FALSE
, FALSE
, 0);
940 ui
->count_label
= GTK_OBJECT (gtk_label_new (""));
941 gtk_box_pack_start (GTK_BOX (hbox
), GTK_WIDGET (ui
->count_label
), FALSE
, FALSE
, 0);
943 gtk_box_pack_start (GTK_BOX (hbox
), gtk_label_new (_("is ")), FALSE
, FALSE
, 0);
944 ui
->file_label
= gtk_label_new ("");
945 gtk_box_pack_start (GTK_BOX (hbox
), ui
->file_label
, FALSE
, FALSE
, 0);
946 gtk_box_pack_start (GTK_BOX (hbox
), gtk_label_new (_("done.")), FALSE
, FALSE
, 0);
947 gtk_container_add (GTK_CONTAINER (alignment
), hbox
);
949 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (ui
->op_win
)->vbox
),
950 alignment
, FALSE
, FALSE
, 0);
952 ui
->byte_prog
= GTK_OBJECT (gtk_progress_bar_new ());
953 gtk_widget_set_usize (GTK_WIDGET (ui
->byte_prog
), GDIALOG_PROGRESS_WIDTH
, -1);
954 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (ui
->op_win
)->vbox
),
955 GTK_WIDGET (ui
->byte_prog
), FALSE
, FALSE
, 0);
957 /* done with things */
958 gtk_widget_show_all (GNOME_DIALOG (ui
->op_win
)->vbox
);
959 gtk_window_set_modal (GTK_WINDOW (ui
->op_win
), TRUE
);
960 gtk_widget_show_now (ui
->op_win
);
964 file_op_context_destroy_ui (FileOpContext
*ctx
)
968 g_return_if_fail (ctx
!= NULL
);
975 gtk_widget_destroy (ui
->op_win
);
982 fmd_init_i18n (int force
)
984 /* unneccessary func */
987 /* Callback for the gnome_request_dialog() in the input dialog */
989 input_dialog_cb (gchar
*string
, gpointer data
)
999 /* Our implementation of the general-purpose input dialog */
1001 real_input_dialog_help (char *header
, char *text
, char *help
, char *def_text
)
1007 if (strncmp (text
, _("Password:"), strlen (_("Password"))) == 0)
1010 is_password
= FALSE
;
1012 dialog
= gnome_request_dialog (is_password
, text
, def_text
, 0,
1013 input_dialog_cb
, &string
,
1015 gtk_window_set_title (GTK_WINDOW (dialog
), header
);
1016 gtk_window_set_modal (GTK_WINDOW (dialog
), TRUE
);
1021 /* Our implementation of the symlink-to dialog */
1023 symlink_dialog (char *existing
, char *new, char **ret_existing
, char **ret_new
)
1028 GtkWidget
*entry1
, *entry2
;
1032 g_return_if_fail (existing
!= NULL
);
1033 g_return_if_fail (new != NULL
);
1034 g_return_if_fail (ret_existing
!= NULL
);
1035 g_return_if_fail (ret_new
!= NULL
);
1037 /* Create the dialog */
1039 dialog
= gnome_dialog_new (_("Symbolic Link"),
1040 GNOME_STOCK_BUTTON_OK
,
1041 GNOME_STOCK_BUTTON_CANCEL
,
1043 gnome_dialog_close_hides (GNOME_DIALOG (dialog
), TRUE
);
1044 gnome_dialog_set_default (GNOME_DIALOG (dialog
), 0);
1047 if (!is_a_desktop_panel (panel
))
1048 gnome_dialog_set_parent (GNOME_DIALOG (dialog
), panel
->xwindow
);
1050 /* File symlink will point to */
1052 vbox
= gtk_vbox_new (FALSE
, GNOME_PAD_SMALL
);
1053 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog
)->vbox
), vbox
, FALSE
, FALSE
, 0);
1055 w
= gtk_label_new (_("Existing filename (filename symlink will point to):"));
1056 gtk_misc_set_alignment (GTK_MISC (w
), 0.0, 0.5);
1057 gtk_box_pack_start (GTK_BOX (vbox
), w
, FALSE
, FALSE
, 0);
1059 entry1
= gtk_entry_new ();
1060 gtk_entry_set_text (GTK_ENTRY (entry1
), existing
);
1061 gtk_box_pack_start (GTK_BOX (vbox
), entry1
, FALSE
, FALSE
, 0);
1062 gnome_dialog_editable_enters (GNOME_DIALOG (dialog
), GTK_EDITABLE (entry1
));
1064 /* Name of symlink */
1066 vbox
= gtk_vbox_new (FALSE
, GNOME_PAD_SMALL
);
1067 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog
)->vbox
), vbox
, FALSE
, FALSE
, 0);
1069 w
= gtk_label_new (_("Symbolic link filename:"));
1070 gtk_misc_set_alignment (GTK_MISC (w
), 0.0, 0.5);
1071 gtk_box_pack_start (GTK_BOX (vbox
), w
, FALSE
, FALSE
, 0);
1073 entry2
= gtk_entry_new ();
1074 gtk_entry_set_text (GTK_ENTRY (entry2
), new);
1075 gtk_box_pack_start (GTK_BOX (vbox
), entry2
, FALSE
, FALSE
, 0);
1076 gnome_dialog_editable_enters (GNOME_DIALOG (dialog
), GTK_EDITABLE (entry2
));
1077 gtk_widget_grab_focus (entry2
);
1081 gtk_widget_show_all (GNOME_DIALOG (dialog
)->vbox
);
1082 ret
= gnome_dialog_run (GNOME_DIALOG (dialog
));
1085 *ret_existing
= NULL
;
1088 *ret_existing
= g_strdup (gtk_entry_get_text (GTK_ENTRY (entry1
)));
1089 *ret_new
= g_strdup (gtk_entry_get_text (GTK_ENTRY (entry2
)));
1093 gtk_widget_destroy (dialog
);