ru.po: Corrections from Evgeny Bulgakov <bgav@netvision.net.il>
[midnight-commander.git] / gnome / gdialogs.c
blobd2b0e8dbac0807b9bd904056e6194c701a36f036
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
2 /* New dialogs... */
3 #include <config.h>
4 #include "panel.h"
5 #include <gnome.h>
6 #include "dialog.h"
7 #include "global.h"
8 #include "file.h"
9 #include "filegui.h"
10 #include "fileopctx.h"
11 #include "eregex.h"
12 #include "main.h"
13 #include "../vfs/vfs.h"
15 enum {
16 REPLACE_PROMPT,
17 REPLACE_ALWAYS,
18 REPLACE_UPDATE,
19 REPLACE_NEVER,
20 REPLACE_ABORT,
21 REPLACE_SIZE,
22 REPLACE_OPTION_MENU
23 } FileReplaceCode;
25 /* This structure describes the UI and internal data required by a file
26 * operation context.
28 typedef struct {
29 /* The progress window */
30 GtkWidget *op_win;
32 /* Set to FALSE in file_op_context_create_ui, set on the cancel_cb if
33 * user click on Cancel.
35 gboolean aborting;
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 */
50 GtkObject *byte_prog;
52 /* Copy status in query replace dialog */
53 int copy_status;
54 int minor_copy_status;
56 /* Overwrite toggle */
57 GtkWidget *op_radio;
58 } FileOpContextUI;
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... */
67 static void
68 fmd_check_box_callback (GtkWidget *widget, gpointer data)
70 if (data)
71 *((gint*)data) = GTK_TOGGLE_BUTTON (widget)->active;
74 static gchar *
75 trim_file_name (FileOpContextUI *ui, gchar *path, gint length, gint cur_length)
77 static gint dotdotdot = 0;
78 gchar *path_copy = NULL;
79 gint len;
81 if (!dotdotdot)
82 dotdotdot = gdk_string_width (ui->op_source_label->style->font, "...");
83 /* Cut the font length of path to length. */
85 length -= dotdotdot;
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)
91 len--;
92 len++;
93 } else {
94 while (gdk_string_width (ui->op_source_label->style->font, path + len) > length)
95 len++;
98 path_copy = g_strdup_printf ("...%s", path + len);
99 return path_copy;
102 FileProgressStatus
103 file_progress_show_source (FileOpContext *ctx, char *path)
105 static gint from_width = 0;
106 FileOpContextUI *ui;
107 gint path_width;
108 gchar *path_copy = NULL;
110 g_return_val_if_fail (ctx != NULL, FILE_CONT);
112 /* ctx->ui might be NULL for background processes */
113 if (ctx->ui == NULL)
114 return FILE_CONT;
116 ui = ctx->ui;
118 g_return_val_if_fail (ui->op_source_label != NULL, FILE_CONT);
120 if (ui->aborting)
121 return FILE_ABORT;
123 if (path == NULL){
124 gtk_label_set_text (GTK_LABEL (ui->op_source_label), "");
125 return FILE_CONT;
128 if (!from_width){
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);
135 else {
136 path_copy = trim_file_name (ui, path, GDIALOG_PROGRESS_WIDTH - from_width,
137 path_width);
139 gtk_label_set_text (GTK_LABEL (ui->op_source_label), path_copy);
140 g_free (path_copy);
143 return FILE_CONT;
146 FileProgressStatus
147 file_progress_show_target (FileOpContext *ctx, char *path)
149 static gint to_width = 0;
150 FileOpContextUI *ui;
151 gint path_width;
152 gchar *path_copy = NULL;
154 g_return_val_if_fail (ctx != NULL, FILE_CONT);
155 /* ctx->ui might be NULL for background processes */
156 if (ctx->ui == NULL)
157 return FILE_CONT;
159 ui = ctx->ui;
161 g_return_val_if_fail (ui->op_target_label != NULL, FILE_CONT);
163 if (ui->aborting)
164 return FILE_ABORT;
166 if (path == NULL){
167 gtk_label_set_text (GTK_LABEL (ui->op_target_label), "");
168 return FILE_CONT;
171 if (!to_width)
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);
177 else {
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);
180 g_free (path_copy);
183 return FILE_CONT;
186 FileProgressStatus
187 file_progress_show_deleting (FileOpContext *ctx, char *path)
189 static gint deleting_width = 0;
190 FileOpContextUI *ui;
191 gint path_width;
192 gchar *path_copy = NULL;
194 g_return_val_if_fail (ctx != NULL, FILE_CONT);
196 /* ctx->ui might be NULL for background processes */
197 if (ctx->ui == NULL)
198 return FILE_CONT;
200 ui = ctx->ui;
202 if (ui->aborting)
203 return FILE_ABORT;
205 if (path == NULL){
206 gtk_label_set_text (GTK_LABEL (ui->op_source_label), "");
207 return FILE_CONT;
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);
217 else {
218 path_copy = trim_file_name (ui, path, GDIALOG_PROGRESS_WIDTH - deleting_width,
219 path_width);
221 gtk_label_set_text (GTK_LABEL (ui->op_source_label), path_copy);
222 g_free (path_copy);
224 return FILE_CONT;
227 FileProgressStatus
228 file_progress_show (FileOpContext *ctx, long done, long total)
230 static gchar count[20];
231 FileOpContextUI *ui;
232 double perc;
234 g_return_val_if_fail (ctx != NULL, FILE_CONT);
236 /* ctx->ui might be NULL for background processes */
237 if (ctx->ui == NULL)
238 return FILE_CONT;
240 ui = ctx->ui;
242 if (ui->aborting)
243 return FILE_ABORT;
245 if (total > 0) {
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 ();
252 return FILE_CONT;
255 FileProgressStatus
256 file_progress_show_count (FileOpContext *ctx, long done, long total)
258 static gchar count[100];
259 FileOpContextUI *ui;
261 g_return_val_if_fail (ctx != NULL, FILE_CONT);
263 /* ctx->ui might be NULL for background processes */
264 if (ctx->ui == NULL)
265 return FILE_CONT;
267 ui = ctx->ui;
269 if (ui->aborting)
270 return FILE_ABORT;
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 ();
276 return FILE_CONT;
279 FileProgressStatus
280 file_progress_show_bytes (FileOpContext *ctx, double done, double total)
282 FileOpContextUI *ui;
283 double perc;
285 g_return_val_if_fail (ctx != NULL, FILE_CONT);
287 /* ctx->ui might be NULL for background processes */
288 if (ctx->ui == NULL)
289 return FILE_CONT;
291 ui = ctx->ui;
293 if (ui->aborting)
294 return FILE_ABORT;
296 if (total == 0.0)
297 perc = 1.0;
298 else
299 perc = done / total;
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 ();
305 return FILE_CONT;
308 static void
309 option_menu_policy_callback (GtkWidget *item, gpointer data)
311 FileOpContextUI *ui;
312 int status;
314 ui = 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);
322 static void
323 policy_callback (GtkWidget *button, gpointer data)
325 FileOpContextUI *ui;
326 int status;
328 ui = 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;
334 } else
335 ui->copy_status = status;
339 FileProgressStatus
340 file_progress_query_replace_policy (FileOpContext *ctx, gboolean dialog_needed)
342 FileOpContextUI *ui;
343 GtkWidget *qrp_dlg;
344 GtkWidget *radio;
345 GtkWidget *vbox;
346 GtkWidget *vbox2;
347 GtkWidget *hbox;
348 GtkWidget *icon;
349 GtkWidget *label;
350 GtkWidget *hrbox;
351 GSList *group = NULL;
352 GtkWidget *omenu;
353 GtkWidget *menu;
354 GtkWidget *menu_item;
356 g_return_val_if_fail (ctx != NULL, FILE_CONT);
358 /* ctx->ui might be NULL for background processes */
359 if (ctx->ui == NULL)
360 return FILE_CONT;
362 ui = ctx->ui;
364 if (ui->aborting)
365 return FILE_ABORT;
367 ui->copy_status = REPLACE_PROMPT;
368 if (dialog_needed == FALSE)
369 return FILE_CONT;
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,
374 NULL);
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))) {
452 case 0:
453 break;
454 case -1:
455 default:
456 ui->copy_status = REPLACE_ABORT;
457 return FILE_ABORT;
459 return FILE_CONT;
462 FileProgressStatus
463 file_progress_real_query_replace (FileOpContext *ctx, enum OperationMode mode, char *destname,
464 struct stat *_s_stat, struct stat *_d_stat)
466 FileOpContextUI *ui;
467 GtkWidget *qr_dlg;
468 gchar msg[128];
469 GtkWidget *label;
471 g_return_val_if_fail (ctx != NULL, FILE_CONT);
472 g_return_val_if_fail (ctx->ui != NULL, FILE_CONT);
474 ui = ctx->ui;
476 if (ui->aborting)
477 return FILE_ABORT;
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))) {
501 case 0:
502 return FILE_CONT;
503 case 1:
504 return FILE_SKIP;
505 default:
506 return FILE_ABORT;
510 switch (ui->copy_status){
511 case REPLACE_UPDATE:
512 if (_s_stat->st_mtime > _d_stat->st_mtime)
513 return FILE_CONT;
514 else
515 return FILE_SKIP;
516 case REPLACE_SIZE:
517 if (_s_stat->st_size == _d_stat->st_size)
518 return FILE_SKIP;
519 else
520 return FILE_CONT;
521 case REPLACE_ALWAYS:
522 return FILE_CONT;
523 case REPLACE_NEVER:
524 return FILE_SKIP;
525 case REPLACE_ABORT:
526 default:
527 return FILE_ABORT;
531 void
532 file_progress_set_stalled_label (FileOpContext *ctx, char *stalled_msg)
534 g_return_if_fail (ctx != NULL);
536 if (ctx->ui == NULL)
537 return;
539 if (!stalled_msg || !*stalled_msg)
540 return;
541 /* FIXME */
542 g_warning ("FIXME: file_progress_set_stalled_label!\nmsg\t%s\n",stalled_msg);
545 char *
546 file_mask_dialog (FileOpContext *ctx, FileOperation operation, char *text, char *def_text,
547 int only_one, int *do_background)
549 GtkWidget *fmd_win;
550 GtkWidget *notebook;
551 GtkWidget *hbox;
552 GtkWidget *vbox, *label;
553 GtkWidget *fentry;
554 GtkWidget *cbox;
555 GtkWidget *icon;
556 int source_easy_patterns = easy_patterns;
557 char *source_mask, *orig_mask, *dest_dir;
558 const char *error;
559 struct stat buf;
560 int run;
562 g_return_val_if_fail (ctx != NULL, NULL);
564 ctx->stable_symlinks = 0;
566 /* Basic window */
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),
582 hbox,
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))),
600 def_text);
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;
610 #if 0
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);
615 #if 0
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.");
619 #endif
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);
622 #endif
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),
628 hbox,
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);
637 #if 0
638 gnome_widget_add_help (cbox, "FIXME: Add something here Miguel");
639 #endif
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);
647 #if 0
648 gnome_widget_add_help (cbox,
649 _("Selecting this will copy the files that symlinks point "
650 "to instead of just copying the link."));
651 #endif
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);
658 #if 0
659 gnome_widget_add_help (cbox,
660 _("Preserves the permissions and the UID/GID if possible"));
661 #endif
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);
671 #if 0
672 gnome_widget_add_help (cbox,
673 _("If set, this will copy the directories recursively"));
674 #endif
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);
687 return NULL;
690 dest_dir = gnome_file_entry_get_full_path (GNOME_FILE_ENTRY (fentry), FALSE);
691 gtk_widget_destroy (fmd_win);
693 easy_patterns = 1;
694 if (!dest_dir || !*dest_dir)
695 return NULL;
697 if (ctx->follow_links && operation != OP_MOVE)
698 ctx->stat_func = mc_stat;
699 else
700 ctx->stat_func = mc_lstat;
702 if (ctx->op_preserve || operation == OP_MOVE){
703 ctx->preserve = 1;
704 ctx->umask_kill = 0777777;
705 ctx->preserve_uidgid = (geteuid () == 0) ? 1 : 0;
706 } else {
707 int i;
708 ctx->preserve = ctx->preserve_uidgid = 0;
709 i = umask (0);
710 umask (i);
711 ctx->umask_kill = i ^ 0777777;
713 source_mask = g_strdup ("*");
714 orig_mask = source_mask;
715 if (!dest_dir || !*dest_dir){
716 if (source_mask)
717 g_free (source_mask);
718 return dest_dir;
721 if (!dest_dir)
722 return NULL;
724 if (!*dest_dir) {
725 g_free (dest_dir);
726 return NULL;
729 if (source_easy_patterns) {
730 source_easy_patterns = easy_patterns;
731 easy_patterns = 1;
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);
736 } else
737 error = re_compile_pattern (source_mask, strlen (source_mask), &ctx->rx);
739 if (error)
740 g_warning ("%s\n",error);
742 if (orig_mask)
743 g_free (orig_mask);
744 ctx->dest_mask = strrchr (dest_dir, PATH_SEP);
745 if (ctx->dest_mask == NULL)
746 ctx->dest_mask = dest_dir;
747 else
748 ctx->dest_mask++;
749 orig_mask = ctx->dest_mask;
750 if (!*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 ("*");
758 else {
759 ctx->dest_mask = g_strdup (ctx->dest_mask);
760 *orig_mask = 0;
762 if (!*dest_dir){
763 g_free (dest_dir);
764 dest_dir = g_strdup ("./");
766 return dest_dir;
770 file_delete_query_recursive (FileOpContext *ctx, enum OperationMode mode, gchar *s)
772 GtkWidget *dialog;
773 GtkWidget *togglebutton;
774 gchar *title;
775 gchar *msg;
776 gint button;
777 gboolean rest_same;
779 if (ctx->recursive_result < RECURSIVE_ALWAYS) {
780 msg = g_strdup_printf (_("%s\n\nDirectory not empty. Delete it recursively?"),
781 name_trunc (s, 80));
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,
787 NULL);
788 g_free (msg);
790 title = g_strconcat (_(" Delete: "), name_trunc (s, 30), " ", NULL);
791 gtk_window_set_title (GTK_WINDOW (dialog), title);
792 g_free (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);
806 switch (button) {
807 case 0:
808 ctx->recursive_result = rest_same ? RECURSIVE_ALWAYS : RECURSIVE_YES;
809 break;
810 case 1:
811 ctx->recursive_result = rest_same ? RECURSIVE_NEVER : RECURSIVE_NO;
812 break;
813 case 2:
814 ctx->recursive_result = RECURSIVE_ABORT;
815 break;
816 default:
819 if (ctx->recursive_result != RECURSIVE_ABORT)
820 do_refresh ();
823 switch (ctx->recursive_result){
824 case RECURSIVE_YES:
825 case RECURSIVE_ALWAYS:
826 return FILE_CONT;
828 case RECURSIVE_NO:
829 case RECURSIVE_NEVER:
830 return FILE_SKIP;
832 case RECURSIVE_ABORT:
834 default:
835 return FILE_ABORT;
839 static void
840 cancel_cb (GtkWidget *widget, gpointer data)
842 FileOpContextUI *ui;
844 ui = data;
845 ui->aborting = TRUE;
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.
852 static gboolean
853 close_cb (GtkWidget *widget, gpointer data)
855 FileOpContextUI *ui;
857 ui = data;
858 ui->aborting = TRUE;
859 return TRUE;
862 void
863 file_op_context_create_ui (FileOpContext *ctx, FileOperation op, int with_eta)
865 FileOpContextUI *ui;
866 GtkWidget *alignment;
867 GtkWidget *hbox;
869 g_return_if_fail (ctx != NULL);
870 g_return_if_fail (ctx->ui == NULL);
872 ui = g_new0 (FileOpContextUI, 1);
873 ctx->ui = ui;
875 switch (op) {
876 case OP_MOVE:
877 ui->op_win = gnome_dialog_new (_("Move Progress"), GNOME_STOCK_BUTTON_CANCEL, NULL);
878 break;
879 case OP_COPY:
880 ui->op_win = gnome_dialog_new (_("Copy Progress"), GNOME_STOCK_BUTTON_CANCEL, NULL);
881 break;
882 case OP_DELETE:
883 ui->op_win = gnome_dialog_new (_("Delete Progress"), GNOME_STOCK_BUTTON_CANCEL, NULL);
884 break;
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),
890 ui);
892 gtk_signal_connect (GTK_OBJECT (ui->op_win), "close",
893 GTK_SIGNAL_FUNC (close_cb),
894 ui);
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)),
901 FALSE, FALSE, 0);
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),
907 GNOME_PAD);
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)),
915 FALSE, FALSE, 0);
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);
921 } else {
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)),
926 FALSE, FALSE, 0);
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),
932 GNOME_PAD);
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);
963 void
964 file_op_context_destroy_ui (FileOpContext *ctx)
966 FileOpContextUI *ui;
968 g_return_if_fail (ctx != NULL);
970 if (ctx->ui == NULL)
971 return;
973 ui = ctx->ui;
975 gtk_widget_destroy (ui->op_win);
977 g_free (ui);
978 ctx->ui = NULL;
981 void
982 fmd_init_i18n (int force)
984 /* unneccessary func */
987 /* Callback for the gnome_request_dialog() in the input dialog */
988 static void
989 input_dialog_cb (gchar *string, gpointer data)
991 char **s;
993 s = data;
994 *s = string;
996 gtk_main_quit ();
999 /* Our implementation of the general-purpose input dialog */
1000 char *
1001 real_input_dialog_help (char *header, char *text, char *help, char *def_text)
1003 int is_password;
1004 GtkWidget *dialog;
1005 char *string;
1007 if (strncmp (text, _("Password:"), strlen (_("Password"))) == 0)
1008 is_password = TRUE;
1009 else
1010 is_password = FALSE;
1012 dialog = gnome_request_dialog (is_password, text, def_text, 0,
1013 input_dialog_cb, &string,
1014 NULL);
1015 gtk_window_set_title (GTK_WINDOW (dialog), header);
1016 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
1017 gtk_main ();
1018 return string;
1021 /* Our implementation of the symlink-to dialog */
1022 void
1023 symlink_dialog (char *existing, char *new, char **ret_existing, char **ret_new)
1025 GtkWidget *dialog;
1026 GtkWidget *vbox;
1027 GtkWidget *w;
1028 GtkWidget *entry1, *entry2;
1029 WPanel *panel;
1030 int ret;
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,
1042 NULL);
1043 gnome_dialog_close_hides (GNOME_DIALOG (dialog), TRUE);
1044 gnome_dialog_set_default (GNOME_DIALOG (dialog), 0);
1046 panel = cpanel;
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);
1079 /* Run */
1081 gtk_widget_show_all (GNOME_DIALOG (dialog)->vbox);
1082 ret = gnome_dialog_run (GNOME_DIALOG (dialog));
1084 if (ret != 0) {
1085 *ret_existing = NULL;
1086 *ret_new = NULL;
1087 } else {
1088 *ret_existing = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry1)));
1089 *ret_new = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry2)));
1092 if (ret != -1)
1093 gtk_widget_destroy (dialog);