Mercurial > geeqie
comparison src/utilops.c @ 753:477f48ba28d8
rewritten utilops.h:
- better integration of external commands
- filter commands
author | nadvornik |
---|---|
date | Sat, 24 May 2008 22:44:18 +0000 |
parents | 2d8a8e892b5e |
children | be382bffd11f |
comparison
equal
deleted
inserted
replaced
752:85c9412d77d2 | 753:477f48ba28d8 |
---|---|
33 #include "ui_tabcomp.h" | 33 #include "ui_tabcomp.h" |
34 #include "editors.h" | 34 #include "editors.h" |
35 | 35 |
36 /* | 36 /* |
37 *-------------------------------------------------------------------------- | 37 *-------------------------------------------------------------------------- |
38 * call these when names change, files move, deleted, etc. | |
39 * so that any open windows are also updated | |
40 *-------------------------------------------------------------------------- | |
41 */ | |
42 | |
43 | |
44 void file_maint_renamed(FileData *fd) | |
45 { | |
46 cache_maint_moved(fd); | |
47 collection_maint_renamed(fd); | |
48 | |
49 layout_maint_renamed(fd); | |
50 view_window_maint_moved(fd); | |
51 dupe_maint_renamed(fd); | |
52 search_maint_renamed(fd); | |
53 } | |
54 | |
55 /* under most cases ignore_list should be NULL */ | |
56 void file_maint_removed(FileData *fd, GList *ignore_list) | |
57 { | |
58 layout_maint_removed(fd, ignore_list); | |
59 view_window_maint_removed(fd, ignore_list); | |
60 dupe_maint_removed(fd); | |
61 search_maint_removed(fd); | |
62 | |
63 collection_maint_removed(fd); | |
64 cache_maint_removed(fd); | |
65 } | |
66 | |
67 /* special case for correct main window behavior */ | |
68 void file_maint_moved(FileData *fd, GList *ignore_list) | |
69 { | |
70 cache_maint_moved(fd); | |
71 collection_maint_renamed(fd); | |
72 | |
73 layout_maint_moved(fd, ignore_list); | |
74 view_window_maint_moved(fd); | |
75 dupe_maint_renamed(fd); | |
76 search_maint_renamed(fd); | |
77 } | |
78 | |
79 void file_maint_copied(FileData *fd) | |
80 { | |
81 cache_maint_copied(fd); | |
82 } | |
83 | |
84 /* | |
85 *-------------------------------------------------------------------------- | |
86 * The file manipulation dialogs | |
87 *-------------------------------------------------------------------------- | |
88 */ | |
89 | |
90 | |
91 enum { | |
92 DIALOG_NEW_DIR, | |
93 DIALOG_COPY, | |
94 DIALOG_MOVE, | |
95 DIALOG_DELETE, | |
96 DIALOG_RENAME | |
97 }; | |
98 | |
99 typedef struct _FileDataMult FileDataMult; | |
100 struct _FileDataMult | |
101 { | |
102 gint confirm_all; | |
103 gint confirmed; | |
104 gint skip; | |
105 GList *source_list; | |
106 GList *source_next; | |
107 gchar *dest_base; | |
108 FileData *source_fd; | |
109 gchar *dest; | |
110 gint copy; | |
111 | |
112 gint rename; | |
113 gint rename_auto; | |
114 gint rename_all; | |
115 | |
116 GtkWidget *rename_box; | |
117 GtkWidget *rename_entry; | |
118 GtkWidget *rename_auto_box; | |
119 | |
120 GtkWidget *yes_all_button; | |
121 }; | |
122 | |
123 typedef struct _FileDataSingle FileDataSingle; | |
124 struct _FileDataSingle | |
125 { | |
126 gint confirmed; | |
127 FileData *source_fd; | |
128 gchar *dest; | |
129 gint copy; | |
130 | |
131 gint rename; | |
132 gint rename_auto; | |
133 | |
134 GtkWidget *rename_box; | |
135 GtkWidget *rename_entry; | |
136 GtkWidget *rename_auto_box; | |
137 }; | |
138 | |
139 /* | |
140 *-------------------------------------------------------------------------- | |
141 * Adds 1 or 2 images (if 2, side by side) to a GenericDialog | 38 * Adds 1 or 2 images (if 2, side by side) to a GenericDialog |
142 *-------------------------------------------------------------------------- | 39 *-------------------------------------------------------------------------- |
143 */ | 40 */ |
144 | 41 |
145 #define DIALOG_DEF_IMAGE_DIM_X 200 | 42 #define DIALOG_DEF_IMAGE_DIM_X 200 |
329 | 226 |
330 return n; | 227 return n; |
331 } | 228 } |
332 | 229 |
333 | 230 |
231 | |
334 /* | 232 /* |
335 *-------------------------------------------------------------------------- | 233 *-------------------------------------------------------------------------- |
336 * Move and Copy routines | 234 * call these when names change, files move, deleted, etc. |
235 * so that any open windows are also updated | |
337 *-------------------------------------------------------------------------- | 236 *-------------------------------------------------------------------------- |
338 */ | 237 */ |
339 | 238 |
340 static gint copy_file_ext_cb(gpointer ed, gint flags, GList *list, gpointer data) | 239 /* FIXME this is a temporary solution */ |
341 { | 240 void file_data_notify_ci(FileData *fd) |
342 if ((flags & EDITOR_ERROR_MASK) && !(flags & EDITOR_ERROR_SKIPPED)) | 241 { |
242 FileDataChangeType type = fd->change->type; | |
243 switch (type) | |
244 { | |
245 case FILEDATA_CHANGE_MOVE: | |
246 cache_maint_moved(fd); | |
247 collection_maint_renamed(fd); | |
248 | |
249 layout_maint_moved(fd, NULL); | |
250 view_window_maint_moved(fd); | |
251 dupe_maint_renamed(fd); | |
252 search_maint_renamed(fd); | |
253 break; | |
254 case FILEDATA_CHANGE_COPY: | |
255 cache_maint_copied(fd); | |
256 break; | |
257 case FILEDATA_CHANGE_RENAME: | |
258 cache_maint_moved(fd); | |
259 collection_maint_renamed(fd); | |
260 | |
261 layout_maint_renamed(fd); | |
262 view_window_maint_moved(fd); | |
263 dupe_maint_renamed(fd); | |
264 search_maint_renamed(fd); | |
265 case FILEDATA_CHANGE_DELETE: | |
266 layout_maint_removed(fd, NULL); | |
267 view_window_maint_removed(fd, NULL); | |
268 dupe_maint_removed(fd); | |
269 search_maint_removed(fd); | |
270 | |
271 collection_maint_removed(fd); | |
272 cache_maint_removed(fd); | |
273 break; | |
274 case FILEDATA_CHANGE_UNSPECIFIED: | |
275 /* FIXME */ | |
276 break; | |
277 } | |
278 } | |
279 | |
280 void file_data_sc_notify_ci(FileData *fd) | |
281 { | |
282 GList *work; | |
283 if (fd->parent) fd = fd->parent; | |
284 | |
285 file_data_notify_ci(fd); | |
286 | |
287 work = fd->sidecar_files; | |
288 while (work) | |
289 { | |
290 FileData *sfd = work->data; | |
291 file_data_notify_ci(sfd); | |
292 work = work->next; | |
293 } | |
294 } | |
295 | |
296 | |
297 typedef enum { | |
298 UTILITY_TYPE_COPY, | |
299 UTILITY_TYPE_MOVE, | |
300 UTILITY_TYPE_RENAME, | |
301 UTILITY_TYPE_EDITOR, | |
302 UTILITY_TYPE_FILTER, | |
303 UTILITY_TYPE_DELETE, | |
304 UTILITY_TYPE_DELETE_LINK, | |
305 UTILITY_TYPE_DELETE_FOLDER | |
306 } UtilityType; | |
307 | |
308 typedef enum { | |
309 UTILITY_PHASE_START = 0, | |
310 UTILITY_PHASE_ENTERING, | |
311 UTILITY_PHASE_CHECKED, | |
312 UTILITY_PHASE_DONE, | |
313 UTILITY_PHASE_CANCEL | |
314 } UtilityPhase; | |
315 | |
316 enum { | |
317 UTILITY_RENAME = 0, | |
318 UTILITY_RENAME_AUTO, | |
319 UTILITY_RENAME_FORMATTED | |
320 }; | |
321 | |
322 typedef struct _UtilityDataMessages UtilityDataMessages; | |
323 struct _UtilityDataMessages { | |
324 gchar *title; | |
325 gchar *question; | |
326 gchar *desc_flist; | |
327 gchar *desc_dlist; | |
328 gchar *desc_source_fd; | |
329 gchar *fail; | |
330 }; | |
331 | |
332 typedef struct _UtilityData UtilityData; | |
333 | |
334 struct _UtilityData { | |
335 UtilityType type; | |
336 UtilityPhase phase; | |
337 | |
338 FileData *source_fd; | |
339 GList *dlist; | |
340 GList *flist; | |
341 | |
342 GtkWidget *parent; | |
343 GenericDialog *gd; | |
344 FileDialog *fdlg; | |
345 | |
346 gint update_idle_id; | |
347 | |
348 /* alternative dialog parts */ | |
349 GtkWidget *notebook; | |
350 | |
351 UtilityDataMessages messages; | |
352 | |
353 /* helper entries for various modes */ | |
354 GtkWidget *rename_entry; | |
355 GtkWidget *rename_label; | |
356 GtkWidget *auto_entry_front; | |
357 GtkWidget *auto_entry_end; | |
358 GtkWidget *auto_spin_start; | |
359 GtkWidget *auto_spin_pad; | |
360 GtkWidget *format_entry; | |
361 GtkWidget *format_spin; | |
362 | |
363 GtkWidget *listview; | |
364 | |
365 | |
366 gchar *dest_path; | |
367 | |
368 /* data for the operation itself, internal or external */ | |
369 gboolean external; /* TRUE for ecternal command, false for internal */ | |
370 | |
371 gint external_command; | |
372 gpointer resume_data; | |
373 | |
374 | |
375 }; | |
376 | |
377 enum { | |
378 UTILITY_COLUMN_FD = 0, | |
379 UTILITY_COLUMN_PATH, | |
380 UTILITY_COLUMN_NAME, | |
381 UTILITY_COLUMN_SIDECARS, | |
382 UTILITY_COLUMN_DEST_PATH, | |
383 UTILITY_COLUMN_DEST_NAME, | |
384 UTILITY_COLUMN_COUNT | |
385 }; | |
386 | |
387 #define UTILITY_LIST_MIN_WIDTH 250 | |
388 #define UTILITY_LIST_MIN_HEIGHT 150 | |
389 | |
390 /* thumbnail spec has a max depth of 4 (.thumb??/fail/appname/??.png) */ | |
391 #define UTILITY_DELETE_MAX_DEPTH 5 | |
392 | |
393 static UtilityData *file_util_data_new(UtilityType type) | |
394 { | |
395 UtilityData *ud; | |
396 | |
397 ud = g_new0(UtilityData, 1); | |
398 ud->type = type; | |
399 ud->phase = UTILITY_PHASE_START; | |
400 ud->update_idle_id = -1; | |
401 ud->external_command = -1; | |
402 return ud; | |
403 } | |
404 | |
405 static void file_util_data_free(UtilityData *ud) | |
406 { | |
407 if (!ud) return; | |
408 | |
409 if (ud->update_idle_id != -1) g_source_remove(ud->update_idle_id); | |
410 | |
411 file_data_unref(ud->source_fd); | |
412 filelist_free(ud->dlist); | |
413 filelist_free(ud->flist); | |
414 | |
415 if (ud->gd) generic_dialog_close(ud->gd); | |
416 | |
417 g_free(ud->dest_path); | |
418 | |
419 g_free(ud); | |
420 } | |
421 | |
422 static GtkTreeViewColumn *file_util_dialog_add_list_column(GtkWidget *view, const gchar *text, gint n) | |
423 { | |
424 GtkTreeViewColumn *column; | |
425 GtkCellRenderer *renderer; | |
426 | |
427 column = gtk_tree_view_column_new(); | |
428 gtk_tree_view_column_set_title(column, text); | |
429 gtk_tree_view_column_set_min_width(column, 4); | |
430 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_GROW_ONLY); | |
431 renderer = gtk_cell_renderer_text_new(); | |
432 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
433 gtk_tree_view_column_add_attribute(column, renderer, "text", n); | |
434 gtk_tree_view_append_column(GTK_TREE_VIEW(view), column); | |
435 | |
436 return column; | |
437 } | |
438 | |
439 static void file_util_dialog_list_select(GtkWidget *view, gint n) | |
440 { | |
441 GtkTreeModel *store; | |
442 GtkTreeIter iter; | |
443 GtkTreeSelection *selection; | |
444 | |
445 store = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); | |
446 if (gtk_tree_model_iter_nth_child(store, &iter, NULL, n)) | |
447 { | |
448 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); | |
449 gtk_tree_selection_select_iter(selection, &iter); | |
450 } | |
451 } | |
452 | |
453 static GtkWidget *file_util_dialog_add_list(GtkWidget *box, GList *list, gint full_paths) | |
454 { | |
455 GtkWidget *scrolled; | |
456 GtkWidget *view; | |
457 GtkListStore *store; | |
458 | |
459 scrolled = gtk_scrolled_window_new(NULL, NULL); | |
460 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); | |
461 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), | |
462 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); | |
463 gtk_box_pack_start(GTK_BOX(box), scrolled, TRUE, TRUE, 0); | |
464 gtk_widget_show(scrolled); | |
465 | |
466 store = gtk_list_store_new(UTILITY_COLUMN_COUNT, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); | |
467 view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); | |
468 g_object_unref(store); | |
469 | |
470 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), TRUE); | |
471 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(view), FALSE); | |
472 | |
473 if (full_paths) | |
474 { | |
475 file_util_dialog_add_list_column(view, _("Location"), UTILITY_COLUMN_PATH); | |
476 } | |
477 else | |
478 { | |
479 file_util_dialog_add_list_column(view, _("Name"), UTILITY_COLUMN_NAME); | |
480 } | |
481 | |
482 gtk_widget_set_size_request(view, UTILITY_LIST_MIN_WIDTH, UTILITY_LIST_MIN_HEIGHT); | |
483 gtk_container_add(GTK_CONTAINER(scrolled), view); | |
484 gtk_widget_show(view); | |
485 | |
486 while (list) | |
343 { | 487 { |
344 FileData *fd = list->data; | 488 FileData *fd = list->data; |
345 gchar *title = _("Error copying file"); | 489 GtkTreeIter iter; |
346 gchar *text = g_strdup_printf(_("%s\nUnable to copy file:\n%s\nto:\n%s"), editor_get_error_str(flags), fd->name, fd->change->dest); | 490 gchar *sidecars; |
347 file_util_warning_dialog(title, text, GTK_STOCK_DIALOG_ERROR, NULL); | 491 |
348 g_free(text); | 492 sidecars = file_data_sc_list_to_string(fd); |
349 } | 493 |
350 while (list) | 494 gtk_list_store_append(store, &iter); |
351 { | 495 gtk_list_store_set(store, &iter, UTILITY_COLUMN_FD, fd, |
352 FileData *fd = list->data; | 496 UTILITY_COLUMN_PATH, fd->path, |
353 if (!(flags & EDITOR_ERROR_MASK)) | 497 UTILITY_COLUMN_NAME, fd->name, |
354 file_maint_copied(fd); | 498 UTILITY_COLUMN_SIDECARS, sidecars, |
355 file_data_change_info_free(NULL, fd); | 499 UTILITY_COLUMN_DEST_PATH, fd->change ? fd->change->dest : "error", |
500 UTILITY_COLUMN_DEST_NAME, fd->change ? filename_from_path(fd->change->dest) : "error", | |
501 -1); | |
502 g_free(sidecars); | |
503 | |
356 list = list->next; | 504 list = list->next; |
357 } | 505 } |
358 return EDITOR_CB_CONTINUE; | 506 |
359 } | 507 return view; |
360 | 508 } |
361 | 509 |
362 gint copy_file_ext(FileData *fd) | 510 // FIXME |
363 { | 511 static void file_util_delete_dir_ok_cb(GenericDialog *gd, gpointer data); |
364 gint ok; | 512 |
365 g_assert(fd->change); | 513 void file_util_perform_ci_internal(UtilityData *ud); |
366 if (options->editor[CMD_COPY].command) | 514 void file_util_dialog_run(UtilityData *ud); |
367 { | 515 static gint file_util_perform_ci_cb(gpointer resume_data, gint flags, GList *list, gpointer data); |
368 ok = !start_editor_from_file_full(CMD_COPY, fd, copy_file_ext_cb, NULL); | 516 |
369 if (ok) return ok; /* that's all for now, let's continue in callback */ | 517 /* call file_util_perform_ci_internal or start_editor_from_filelist_full */ |
370 } | 518 |
519 | |
520 static void file_util_resume_cb(GenericDialog *gd, gpointer data) | |
521 { | |
522 UtilityData *ud = data; | |
523 if (ud->external) | |
524 editor_resume(ud->resume_data); | |
371 else | 525 else |
372 ok = copy_file(fd->change->source, fd->change->dest); | 526 file_util_perform_ci_internal(ud); |
373 | 527 } |
374 if (ok) | 528 |
375 { | 529 static void file_util_abort_cb(GenericDialog *gd, gpointer data) |
376 file_maint_copied(fd); | 530 { |
377 } | 531 UtilityData *ud = data; |
378 | 532 if (ud->external) |
379 file_data_change_info_free(NULL, fd); | 533 editor_skip(ud->resume_data); |
380 | |
381 return ok; | |
382 } | |
383 | |
384 static gint move_file_ext_cb(gpointer ed, gint flags, GList *list, gpointer data) | |
385 { | |
386 if ((flags & EDITOR_ERROR_MASK) && !(flags & EDITOR_ERROR_SKIPPED)) | |
387 { | |
388 FileData *fd = list->data; | |
389 gchar *title = _("Error moving file"); | |
390 gchar *text = g_strdup_printf(_("%s\nUnable to move file:\n%s\nto:\n%s"), editor_get_error_str(flags), fd->name, fd->change->dest); | |
391 file_util_warning_dialog(title, text, GTK_STOCK_DIALOG_ERROR, NULL); | |
392 g_free(text); | |
393 } | |
394 while (list) | |
395 { | |
396 FileData *fd = list->data; | |
397 if (!(flags & EDITOR_ERROR_MASK)) | |
398 { | |
399 file_data_sc_apply_ci(fd); | |
400 file_maint_moved(fd, NULL); | |
401 } | |
402 file_data_change_info_free(NULL, fd); | |
403 list = list->next; | |
404 } | |
405 return EDITOR_CB_CONTINUE; | |
406 | |
407 } | |
408 | |
409 | |
410 gint move_file_ext(FileData *fd) | |
411 { | |
412 gint ok; | |
413 g_assert(fd->change); | |
414 if (options->editor[CMD_MOVE].command) | |
415 { | |
416 ok = !start_editor_from_file_full(CMD_MOVE, fd, move_file_ext_cb, NULL); | |
417 if (ok) return ok; /* that's all for now, let's continue in callback */ | |
418 } | |
419 else | 534 else |
420 ok = move_file(fd->change->source, fd->change->dest); | 535 file_util_perform_ci_cb(NULL, EDITOR_ERROR_SKIPPED, ud->flist, ud); |
421 | 536 |
422 if (ok) | 537 } |
423 { | 538 |
424 file_data_sc_apply_ci(fd); | 539 |
425 file_maint_moved(fd, NULL); | 540 static gint file_util_perform_ci_cb(gpointer resume_data, gint flags, GList *list, gpointer data) |
426 } | 541 { |
427 | 542 UtilityData *ud = data; |
428 file_data_change_info_free(NULL, fd); | 543 ud->resume_data = resume_data; |
429 | 544 |
430 return ok; | |
431 } | |
432 | |
433 static gint rename_file_ext_cb(gpointer ed, gint flags, GList *list, gpointer data) | |
434 { | |
435 if ((flags & EDITOR_ERROR_MASK) && !(flags & EDITOR_ERROR_SKIPPED)) | |
436 { | |
437 FileData *fd = list->data; | |
438 gchar *title = _("Error renaming file"); | |
439 gchar *text = g_strdup_printf(_("%s\nUnable to rename file:\n%s\nto:\n%s"), editor_get_error_str(flags), fd->name, fd->change->dest); | |
440 file_util_warning_dialog(title, text, GTK_STOCK_DIALOG_ERROR, NULL); | |
441 g_free(text); | |
442 } | |
443 while (list) | |
444 { | |
445 FileData *fd = list->data; | |
446 if (!(flags & EDITOR_ERROR_MASK)) | |
447 { | |
448 file_data_sc_apply_ci(fd); | |
449 file_maint_renamed(fd); | |
450 } | |
451 file_data_change_info_free(NULL, fd); | |
452 list = list->next; | |
453 } | |
454 return EDITOR_CB_CONTINUE; | |
455 } | |
456 | |
457 gint rename_file_ext(FileData *fd) | |
458 { | |
459 gint ok; | |
460 g_assert(fd->change); | |
461 if (options->editor[CMD_RENAME].command) | |
462 { | |
463 ok = !start_editor_from_file_full(CMD_RENAME, fd, rename_file_ext_cb, NULL); | |
464 if (ok) return ok; /* that's all for now, let's continue in callback */ | |
465 } | |
466 else | |
467 ok = rename_file(fd->change->source, fd->change->dest); | |
468 | |
469 if (ok) | |
470 { | |
471 file_data_sc_apply_ci(fd); | |
472 file_maint_renamed(fd); | |
473 } | |
474 | |
475 file_data_change_info_free(NULL, fd); | |
476 | |
477 return ok; | |
478 } | |
479 | |
480 | |
481 /* | |
482 * Multi file move | |
483 */ | |
484 | |
485 static FileDataMult *file_data_multiple_new(GList *source_list, const gchar *dest, gint copy) | |
486 { | |
487 FileDataMult *fdm = g_new0(FileDataMult, 1); | |
488 fdm->confirm_all = FALSE; | |
489 fdm->confirmed = FALSE; | |
490 fdm->skip = FALSE; | |
491 fdm->source_list = source_list; | |
492 fdm->source_next = fdm->source_list; | |
493 fdm->dest_base = g_strdup(dest); | |
494 fdm->source_fd = NULL; | |
495 fdm->dest = NULL; | |
496 fdm->copy = copy; | |
497 return fdm; | |
498 } | |
499 | |
500 static void file_data_multiple_free(FileDataMult *fdm) | |
501 { | |
502 filelist_free(fdm->source_list); | |
503 g_free(fdm->dest_base); | |
504 g_free(fdm->dest); | |
505 g_free(fdm); | |
506 } | |
507 | |
508 static void file_util_move_multiple(FileDataMult *fdm); | |
509 | |
510 static void file_util_move_multiple_ok_cb(GenericDialog *gd, gpointer data) | |
511 { | |
512 FileDataMult *fdm = data; | |
513 | |
514 fdm->confirmed = TRUE; | |
515 | |
516 if (fdm->rename_auto) | |
517 { | |
518 gchar *buf; | |
519 | |
520 buf = unique_filename_simple(fdm->dest); | |
521 if (buf) | |
522 { | |
523 g_free(fdm->dest); | |
524 fdm->dest = buf; | |
525 } | |
526 else | |
527 { | |
528 /* unique failed? well, return to the overwrite prompt :( */ | |
529 fdm->confirmed = FALSE; | |
530 } | |
531 } | |
532 else if (fdm->rename) | |
533 { | |
534 const gchar *name; | |
535 | |
536 name = gtk_entry_get_text(GTK_ENTRY(fdm->rename_entry)); | |
537 if (strlen(name) == 0 || | |
538 strcmp(name, fdm->source_fd->name) == 0) | |
539 { | |
540 fdm->confirmed = FALSE; | |
541 } | |
542 else | |
543 { | |
544 g_free(fdm->dest); | |
545 fdm->dest = g_build_filename(fdm->dest_base, name, NULL); | |
546 fdm->confirmed = !isname(fdm->dest); | |
547 } | |
548 } | |
549 | |
550 file_util_move_multiple(fdm); | |
551 } | |
552 | |
553 static void file_util_move_multiple_all_cb(GenericDialog *gd, gpointer data) | |
554 { | |
555 FileDataMult *fdm = data; | |
556 | |
557 fdm->confirm_all = TRUE; | |
558 | |
559 if (fdm->rename_auto) fdm->rename_all = TRUE; | |
560 | |
561 file_util_move_multiple(fdm); | |
562 } | |
563 | |
564 static void file_util_move_multiple_skip_cb(GenericDialog *gd, gpointer data) | |
565 { | |
566 FileDataMult *fdm = data; | |
567 | |
568 fdm->skip = TRUE; | |
569 fdm->confirmed = TRUE; | |
570 | |
571 file_util_move_multiple(fdm); | |
572 } | |
573 | |
574 static void file_util_move_multiple_skip_all_cb(GenericDialog *gd, gpointer data) | |
575 { | |
576 FileDataMult *fdm = data; | |
577 | |
578 fdm->skip = TRUE; | |
579 fdm->confirm_all = TRUE; | |
580 file_util_move_multiple(fdm); | |
581 } | |
582 | |
583 static void file_util_move_multiple_continue_cb(GenericDialog *gd, gpointer data) | |
584 { | |
585 FileDataMult *fdm = data; | |
586 | |
587 fdm->confirmed = TRUE; | |
588 file_util_move_multiple(fdm); | |
589 } | |
590 | |
591 static void file_util_move_multiple_cancel_cb(GenericDialog *gd, gpointer data) | |
592 { | |
593 FileDataMult *fdm = data; | |
594 | |
595 file_data_multiple_free(fdm); | |
596 } | |
597 | |
598 /* rename option */ | |
599 | |
600 static void file_util_move_multiple_rename_auto_cb(GtkWidget *widget, gpointer data) | |
601 { | |
602 GenericDialog *gd = data; | |
603 FileDataMult *fdm; | |
604 | |
605 fdm = gd->data; | |
606 | |
607 fdm->rename_auto = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); | |
608 gtk_widget_set_sensitive(fdm->rename_box, !fdm->rename_auto); | |
609 gtk_widget_set_sensitive(fdm->rename_entry, (!fdm->rename_auto && fdm->rename)); | |
610 | |
611 if (fdm->rename_auto) | |
612 { | |
613 gchar *preview; | |
614 | |
615 preview = unique_filename_simple(fdm->dest); | |
616 if (preview) gtk_entry_set_text(GTK_ENTRY(fdm->rename_entry), filename_from_path(preview)); | |
617 g_free(preview); | |
618 } | |
619 | |
620 gtk_widget_set_sensitive(fdm->yes_all_button, (fdm->rename_auto || !fdm->rename)); | |
621 } | |
622 | |
623 static void file_util_move_multiple_rename_cb(GtkWidget *widget, gpointer data) | |
624 { | |
625 GenericDialog *gd = data; | |
626 FileDataMult *fdm; | |
627 | |
628 fdm = gd->data; | |
629 | |
630 fdm->rename = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); | |
631 gtk_widget_set_sensitive(fdm->rename_entry, fdm->rename); | |
632 gtk_widget_set_sensitive(fdm->yes_all_button, !fdm->rename); | |
633 | |
634 if (fdm->rename) | |
635 { | |
636 const gchar *name; | |
637 | |
638 gtk_widget_grab_focus(fdm->rename_entry); | |
639 | |
640 name = gtk_entry_get_text(GTK_ENTRY(fdm->rename_entry)); | |
641 gtk_editable_select_region(GTK_EDITABLE(fdm->rename_entry), 0, filename_base_length(name)); | |
642 } | |
643 } | |
644 | |
645 static GenericDialog *file_util_move_multiple_confirm_dialog(FileDataMult *fdm) | |
646 { | |
647 GenericDialog *gd; | |
648 GtkWidget *hbox; | |
649 | |
650 gd = file_util_gen_dlg(_("Overwrite file"), GQ_WMCLASS, "dlg_confirm", | |
651 NULL, TRUE, | |
652 file_util_move_multiple_cancel_cb, fdm); | |
653 | |
654 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, | |
655 _("Overwrite file?"), | |
656 _("Replace existing file with new file.")); | |
657 pref_spacer(gd->vbox, 0); | |
658 | |
659 generic_dialog_add_button(gd, GTK_STOCK_YES, _("_Overwrite"), file_util_move_multiple_ok_cb, TRUE); | |
660 fdm->yes_all_button = generic_dialog_add_button(gd, NULL, _("Overwrite _all"), | |
661 file_util_move_multiple_all_cb, FALSE); | |
662 generic_dialog_add_button(gd, GTK_STOCK_GOTO_LAST, _("S_kip all"), file_util_move_multiple_skip_all_cb, FALSE); | |
663 generic_dialog_add_button(gd, GTK_STOCK_GO_FORWARD, _("_Skip"), file_util_move_multiple_skip_cb, FALSE); | |
664 generic_dialog_add_image(gd, NULL, file_data_new_simple(fdm->dest), _("Existing file"), fdm->source_fd, _("New file"), TRUE); | |
665 | |
666 /* rename option */ | |
667 | |
668 fdm->rename = FALSE; | |
669 fdm->rename_all = FALSE; | |
670 fdm->rename_auto = FALSE; | |
671 | |
672 hbox = pref_box_new(gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_GAP); | |
673 | |
674 fdm->rename_auto_box = gtk_check_button_new_with_label(_("Auto rename")); | |
675 g_signal_connect(G_OBJECT(fdm->rename_auto_box), "clicked", | |
676 G_CALLBACK(file_util_move_multiple_rename_auto_cb), gd); | |
677 gtk_box_pack_start(GTK_BOX(hbox), fdm->rename_auto_box, FALSE, FALSE, 0); | |
678 gtk_widget_show(fdm->rename_auto_box); | |
679 | |
680 hbox = pref_box_new(gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_GAP); | |
681 | |
682 fdm->rename_box = gtk_check_button_new_with_label(_("Rename")); | |
683 g_signal_connect(G_OBJECT(fdm->rename_box), "clicked", | |
684 G_CALLBACK(file_util_move_multiple_rename_cb), gd); | |
685 gtk_box_pack_start(GTK_BOX(hbox), fdm->rename_box, FALSE, FALSE, 0); | |
686 gtk_widget_show(fdm->rename_box); | |
687 | |
688 fdm->rename_entry = gtk_entry_new(); | |
689 gtk_entry_set_text(GTK_ENTRY(fdm->rename_entry), filename_from_path(fdm->dest)); | |
690 gtk_widget_set_sensitive(fdm->rename_entry, FALSE); | |
691 gtk_box_pack_start(GTK_BOX(hbox), fdm->rename_entry, TRUE, TRUE, 0); | |
692 gtk_widget_show(fdm->rename_entry); | |
693 | |
694 return gd; | |
695 } | |
696 | |
697 static void file_util_move_multiple(FileDataMult *fdm) | |
698 { | |
699 while (fdm->dest || fdm->source_next) | |
700 { | |
701 gint success = FALSE; | |
702 gint skip_file = FALSE; | |
703 | |
704 if (!fdm->dest) | |
705 { | |
706 GList *work = fdm->source_next; | |
707 fdm->source_fd = work->data; | |
708 fdm->dest = g_build_filename(fdm->dest_base, fdm->source_fd->name, NULL); | |
709 fdm->source_next = work->next; | |
710 fdm->confirmed = FALSE; | |
711 } | |
712 | |
713 if (fdm->dest && fdm->source_fd && strcmp(fdm->dest, fdm->source_fd->name) == 0) | |
714 { | |
715 if (!fdm->confirmed) | |
716 { | |
717 GenericDialog *gd; | |
718 const gchar *title; | |
719 gchar *text; | |
720 | |
721 if (fdm->copy) | |
722 { | |
723 title = _("Source to copy matches destination"); | |
724 text = g_strdup_printf(_("Unable to copy file:\n%s\nto itself."), fdm->dest); | |
725 } | |
726 else | |
727 { | |
728 title = _("Source to move matches destination"); | |
729 text = g_strdup_printf(_("Unable to move file:\n%s\nto itself."), fdm->dest); | |
730 } | |
731 | |
732 gd = file_util_gen_dlg(title, GQ_WMCLASS, "dlg_confirm", | |
733 NULL, TRUE, | |
734 file_util_move_multiple_cancel_cb, fdm); | |
735 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_WARNING, title, text); | |
736 g_free(text); | |
737 generic_dialog_add_button(gd, GTK_STOCK_GO_FORWARD, _("Co_ntinue"), | |
738 file_util_move_multiple_continue_cb, TRUE); | |
739 | |
740 gtk_widget_show(gd->dialog); | |
741 return; | |
742 } | |
743 skip_file = TRUE; | |
744 } | |
745 else if (isfile(fdm->dest)) | |
746 { | |
747 if (!fdm->confirmed && !fdm->confirm_all) | |
748 { | |
749 GenericDialog *gd; | |
750 | |
751 gd = file_util_move_multiple_confirm_dialog(fdm); | |
752 gtk_widget_show(gd->dialog); | |
753 return; | |
754 } | |
755 if (fdm->skip) skip_file = TRUE; | |
756 } | |
757 | |
758 if (skip_file) | |
759 { | |
760 success = TRUE; | |
761 if (!fdm->confirm_all) fdm->skip = FALSE; | |
762 } | |
763 else | |
764 { | |
765 gint try = TRUE; | |
766 | |
767 if (fdm->confirm_all && fdm->rename_all && isfile(fdm->dest)) | |
768 { | |
769 gchar *buf; | |
770 buf = unique_filename_simple(fdm->dest); | |
771 if (buf) | |
772 { | |
773 g_free(fdm->dest); | |
774 fdm->dest = buf; | |
775 } | |
776 else | |
777 { | |
778 try = FALSE; | |
779 } | |
780 } | |
781 if (try) | |
782 { | |
783 if (fdm->copy) | |
784 { | |
785 if (file_data_add_change_info(fdm->source_fd, FILEDATA_CHANGE_COPY, fdm->source_fd->path, fdm->dest) && | |
786 copy_file_ext(fdm->source_fd)) | |
787 { | |
788 success = TRUE; | |
789 } | |
790 } | |
791 else | |
792 { | |
793 if (file_data_add_change_info(fdm->source_fd, FILEDATA_CHANGE_MOVE, fdm->source_fd->path, fdm->dest) && | |
794 move_file_ext(fdm->source_fd)) | |
795 { | |
796 success = TRUE; | |
797 } | |
798 } | |
799 | |
800 } | |
801 } | |
802 if (!success) | |
803 { | |
804 GenericDialog *gd; | |
805 const gchar *title; | |
806 gchar *text; | |
807 | |
808 if (fdm->copy) | |
809 { | |
810 title = _("Error copying file"); | |
811 text = g_strdup_printf(_("Unable to copy file:\n%s\nto:\n%s\nduring multiple file copy."), fdm->source_fd->path, fdm->dest); | |
812 } | |
813 else | |
814 { | |
815 title = _("Error moving file"); | |
816 text = g_strdup_printf(_("Unable to move file:\n%s\nto:\n%s\nduring multiple file move."), fdm->source_fd->path, fdm->dest); | |
817 } | |
818 gd = file_util_gen_dlg(title, GQ_WMCLASS, "dlg_confirm", | |
819 NULL, TRUE, | |
820 file_util_move_multiple_cancel_cb, fdm); | |
821 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_WARNING, title, text); | |
822 g_free(text); | |
823 | |
824 generic_dialog_add_button(gd, GTK_STOCK_GO_FORWARD, _("Co_ntinue"), | |
825 file_util_move_multiple_continue_cb, TRUE); | |
826 gtk_widget_show(gd->dialog); | |
827 } | |
828 | |
829 g_free(fdm->dest); | |
830 fdm->dest = NULL; | |
831 | |
832 if (!success) return; | |
833 } | |
834 /* | |
835 if (fdm->source_list) | |
836 file_util_do_move_list(fdm->source_list, fdm->copy); | |
837 else | |
838 { | |
839 GList *list = g_list_append(NULL, file_data_ref(fdm->source_fd)); | |
840 file_util_do_move_list(list, fdm->copy); | |
841 filelist_free(list); | |
842 } | |
843 */ | |
844 file_data_multiple_free(fdm); | |
845 } | |
846 | |
847 /* | |
848 * Single file move | |
849 */ | |
850 | |
851 static FileDataSingle *file_data_single_new(FileData *source_fd, const gchar *dest, gint copy) | |
852 { | |
853 FileDataSingle *fds = g_new0(FileDataSingle, 1); | |
854 fds->confirmed = FALSE; | |
855 fds->source_fd = file_data_ref(source_fd); | |
856 fds->dest = g_strdup(dest); | |
857 fds->copy = copy; | |
858 return fds; | |
859 } | |
860 | |
861 static void file_data_single_free(FileDataSingle *fds) | |
862 { | |
863 file_data_unref(fds->source_fd); | |
864 g_free(fds->dest); | |
865 g_free(fds); | |
866 } | |
867 | |
868 static void file_util_move_single(FileDataSingle *fds); | |
869 | |
870 static void file_util_move_single_ok_cb(GenericDialog *gd, gpointer data) | |
871 { | |
872 FileDataSingle *fds = data; | |
873 | |
874 fds->confirmed = TRUE; | |
875 | |
876 if (fds->rename_auto) | |
877 { | |
878 gchar *buf; | |
879 | |
880 buf = unique_filename_simple(fds->dest); | |
881 if (buf) | |
882 { | |
883 g_free(fds->dest); | |
884 fds->dest = buf; | |
885 } | |
886 else | |
887 { | |
888 /* unique failed? well, return to the overwrite prompt :( */ | |
889 fds->confirmed = FALSE; | |
890 } | |
891 } | |
892 else if (fds->rename) | |
893 { | |
894 const gchar *name; | |
895 | |
896 name = gtk_entry_get_text(GTK_ENTRY(fds->rename_entry)); | |
897 if (strlen(name) == 0 || | |
898 strcmp(name, fds->source_fd->name) == 0) | |
899 { | |
900 fds->confirmed = FALSE; | |
901 } | |
902 else | |
903 { | |
904 gchar *base; | |
905 | |
906 base = remove_level_from_path(fds->dest); | |
907 g_free(fds->dest); | |
908 fds->dest = g_build_filename(base, name, NULL); | |
909 fds->confirmed = !isname(fds->dest); | |
910 | |
911 g_free(base); | |
912 } | |
913 } | |
914 | |
915 file_util_move_single(fds); | |
916 } | |
917 | |
918 static void file_util_move_single_cancel_cb(GenericDialog *gd, gpointer data) | |
919 { | |
920 FileDataSingle *fds = data; | |
921 | |
922 file_data_single_free(fds); | |
923 } | |
924 | |
925 static void file_util_move_single_rename_auto_cb(GtkWidget *widget, gpointer data) | |
926 { | |
927 GenericDialog *gd = data; | |
928 FileDataSingle *fds; | |
929 | |
930 fds = gd->data; | |
931 | |
932 fds->rename_auto = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); | |
933 gtk_widget_set_sensitive(fds->rename_box, !fds->rename_auto); | |
934 gtk_widget_set_sensitive(fds->rename_entry, (!fds->rename_auto && fds->rename)); | |
935 | |
936 if (fds->rename_auto) | |
937 { | |
938 gchar *preview; | |
939 | |
940 preview = unique_filename_simple(fds->dest); | |
941 if (preview) gtk_entry_set_text(GTK_ENTRY(fds->rename_entry), filename_from_path(preview)); | |
942 g_free(preview); | |
943 } | |
944 } | |
945 | |
946 static void file_util_move_single_rename_cb(GtkWidget *widget, gpointer data) | |
947 { | |
948 GenericDialog *gd = data; | |
949 FileDataSingle *fds; | |
950 | |
951 fds = gd->data; | |
952 | |
953 fds->rename = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); | |
954 gtk_widget_set_sensitive(fds->rename_entry, fds->rename); | |
955 | |
956 if (fds->rename) | |
957 { | |
958 const gchar *name; | |
959 | |
960 gtk_widget_grab_focus(fds->rename_entry); | |
961 | |
962 name = gtk_entry_get_text(GTK_ENTRY(fds->rename_entry)); | |
963 gtk_editable_select_region(GTK_EDITABLE(fds->rename_entry), 0, filename_base_length(name)); | |
964 } | |
965 } | |
966 | |
967 static void file_util_move_single(FileDataSingle *fds) | |
968 { | |
969 if (fds->dest && fds->source_fd && strcmp(fds->dest, fds->source_fd->name) == 0) | |
970 { | |
971 file_util_warning_dialog(_("Source matches destination"), | |
972 _("Source and destination are the same, operation cancelled."), | |
973 GTK_STOCK_DIALOG_INFO, NULL); | |
974 } | |
975 else if (isfile(fds->dest) && !fds->confirmed) | |
976 { | |
977 GenericDialog *gd; | |
978 GtkWidget *hbox; | |
979 | |
980 gd = file_util_gen_dlg(_("Overwrite file"), GQ_WMCLASS, "dlg_confirm", | |
981 NULL, TRUE, | |
982 file_util_move_single_cancel_cb, fds); | |
983 | |
984 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, | |
985 _("Overwrite file?"), | |
986 _("Replace existing file with new file.")); | |
987 pref_spacer(gd->vbox, 0); | |
988 | |
989 generic_dialog_add_button(gd, GTK_STOCK_OK, _("_Overwrite"), file_util_move_single_ok_cb, TRUE); | |
990 generic_dialog_add_image(gd, NULL, file_data_new_simple(fds->dest), _("Existing file"), fds->source_fd, _("New file"), TRUE); | |
991 | |
992 /* rename option */ | |
993 | |
994 fds->rename = FALSE; | |
995 fds->rename_auto = FALSE; | |
996 | |
997 hbox = pref_box_new(gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_GAP); | |
998 | |
999 fds->rename_auto_box = gtk_check_button_new_with_label(_("Auto rename")); | |
1000 g_signal_connect(G_OBJECT(fds->rename_auto_box), "clicked", | |
1001 G_CALLBACK(file_util_move_single_rename_auto_cb), gd); | |
1002 gtk_box_pack_start(GTK_BOX(hbox), fds->rename_auto_box, FALSE, FALSE, 0); | |
1003 gtk_widget_show(fds->rename_auto_box); | |
1004 | |
1005 hbox = pref_box_new(gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_GAP); | |
1006 | |
1007 fds->rename_box = gtk_check_button_new_with_label(_("Rename")); | |
1008 g_signal_connect(G_OBJECT(fds->rename_box), "clicked", | |
1009 G_CALLBACK(file_util_move_single_rename_cb), gd); | |
1010 gtk_box_pack_start(GTK_BOX(hbox), fds->rename_box, FALSE, FALSE, 0); | |
1011 gtk_widget_show(fds->rename_box); | |
1012 | |
1013 fds->rename_entry = gtk_entry_new(); | |
1014 gtk_entry_set_text(GTK_ENTRY(fds->rename_entry), filename_from_path(fds->dest)); | |
1015 gtk_widget_set_sensitive(fds->rename_entry, FALSE); | |
1016 gtk_box_pack_start(GTK_BOX(hbox), fds->rename_entry, TRUE, TRUE, 0); | |
1017 gtk_widget_show(fds->rename_entry); | |
1018 | |
1019 gtk_widget_show(gd->dialog); | |
1020 return; | |
1021 } | |
1022 else | |
1023 { | |
1024 gint success = FALSE; | |
1025 if (fds->copy) | |
1026 { | |
1027 if (file_data_add_change_info(fds->source_fd, FILEDATA_CHANGE_COPY, fds->source_fd->path, fds->dest) && | |
1028 copy_file_ext(fds->source_fd)) | |
1029 { | |
1030 success = TRUE; | |
1031 } | |
1032 } | |
1033 else | |
1034 { | |
1035 if (file_data_add_change_info(fds->source_fd, FILEDATA_CHANGE_MOVE, fds->source_fd->path, fds->dest) && | |
1036 move_file_ext(fds->source_fd)) | |
1037 { | |
1038 success = TRUE; | |
1039 } | |
1040 } | |
1041 if (!success) | |
1042 { | |
1043 gchar *title; | |
1044 gchar *text; | |
1045 if (fds->copy) | |
1046 { | |
1047 title = _("Error copying file"); | |
1048 text = g_strdup_printf(_("Unable to copy file:\n%s\nto:\n%s"), fds->source_fd->name, fds->dest); | |
1049 } | |
1050 else | |
1051 { | |
1052 title = _("Error moving file"); | |
1053 text = g_strdup_printf(_("Unable to move file:\n%s\nto:\n%s"), fds->source_fd->name, fds->dest); | |
1054 } | |
1055 file_util_warning_dialog(title, text, GTK_STOCK_DIALOG_ERROR, NULL); | |
1056 g_free(text); | |
1057 } | |
1058 } | |
1059 | |
1060 file_data_single_free(fds); | |
1061 } | |
1062 | |
1063 /* | |
1064 * file move dialog | |
1065 */ | |
1066 | |
1067 static void file_util_move_do(FileDialog *fdlg) | |
1068 { | |
1069 file_dialog_sync_history(fdlg, TRUE); | |
1070 | |
1071 if (fdlg->multiple_files) | |
1072 { | |
1073 file_util_move_multiple(file_data_multiple_new(fdlg->source_list, fdlg->dest_path, fdlg->type)); | |
1074 fdlg->source_list = NULL; | |
1075 } | |
1076 else | |
1077 { | |
1078 if (isdir(fdlg->dest_path)) | |
1079 { | |
1080 gchar *buf = g_build_filename(fdlg->dest_path, fdlg->source_fd->name, NULL); | |
1081 gtk_entry_set_text(GTK_ENTRY(fdlg->entry), buf); | |
1082 g_free(buf); | |
1083 } | |
1084 file_util_move_single(file_data_single_new(fdlg->source_fd, fdlg->dest_path, fdlg->type)); | |
1085 } | |
1086 | |
1087 file_dialog_close(fdlg); | |
1088 } | |
1089 | |
1090 static void file_util_move_check(FileDialog *fdlg) | |
1091 { | |
1092 if (fdlg->dest_path && strcmp(fdlg->dest_path, "~") == 0) | |
1093 { | |
1094 gtk_entry_set_text(GTK_ENTRY(fdlg->entry), homedir()); | |
1095 } | |
1096 | |
1097 if (fdlg->multiple_files && !isdir(fdlg->dest_path)) | |
1098 { | |
1099 if (isfile(fdlg->dest_path)) | |
1100 { | |
1101 file_util_warning_dialog(_("Invalid destination"), | |
1102 _("When operating with multiple files, please select\na folder, not a file."), | |
1103 GTK_STOCK_DIALOG_INFO, NULL); | |
1104 } | |
1105 else | |
1106 file_util_warning_dialog(_("Invalid folder"), | |
1107 _("Please select an existing folder."), | |
1108 GTK_STOCK_DIALOG_INFO, NULL); | |
1109 return; | |
1110 } | |
1111 | |
1112 if (!fdlg->dest_path || fdlg->dest_path[0] != G_DIR_SEPARATOR) | |
1113 { | |
1114 if (fdlg->source_fd) | |
1115 { | |
1116 gchar *base; | |
1117 gchar *path; | |
1118 | |
1119 base = remove_level_from_path(fdlg->source_fd->path); | |
1120 path = g_build_filename(base, fdlg->dest_path, NULL); | |
1121 | |
1122 gtk_entry_set_text(GTK_ENTRY(fdlg->entry), path); | |
1123 | |
1124 g_free(path); | |
1125 g_free(base); | |
1126 } | |
1127 return; | |
1128 } | |
1129 | |
1130 file_util_move_do(fdlg); | |
1131 } | |
1132 | |
1133 static void file_util_move_cb(FileDialog *fdlg, gpointer data) | |
1134 { | |
1135 file_util_move_check(fdlg); | |
1136 } | |
1137 | |
1138 static void file_util_move_cancel_cb(FileDialog *fdlg, gpointer data) | |
1139 { | |
1140 file_dialog_close(fdlg); | |
1141 } | |
1142 | |
1143 static void real_file_util_move(FileData *source_fd, GList *source_list, | |
1144 const gchar *dest_path, gint copy, GtkWidget *parent) | |
1145 { | |
1146 FileDialog *fdlg; | |
1147 GtkWidget *label; | |
1148 FileData *fd = NULL; | |
1149 gint multiple; | |
1150 const gchar *text; | |
1151 gchar *title; | |
1152 const gchar *op_text; | |
1153 const gchar *stock_id; | |
1154 | |
1155 if (!source_fd && !source_list) return; | |
1156 | |
1157 if (source_fd) | |
1158 { | |
1159 fd = file_data_ref(source_fd); | |
1160 multiple = FALSE; | |
1161 } | |
1162 else if (source_list->next) | |
1163 { | |
1164 multiple = TRUE; | |
1165 } | |
1166 else | |
1167 { | |
1168 fd = file_data_ref(source_list->data); | |
1169 filelist_free(source_list); | |
1170 source_list = NULL; | |
1171 multiple = FALSE; | |
1172 } | |
1173 | |
1174 if (copy) | |
1175 { | |
1176 title = _("Copy"); | |
1177 op_text = _("_Copy"); | |
1178 if (fd) | |
1179 { | |
1180 text = _("Copy file"); | |
1181 } | |
1182 else | |
1183 { | |
1184 text = _("Copy multiple files"); | |
1185 } | |
1186 stock_id = GTK_STOCK_COPY; | |
1187 } | |
1188 else | |
1189 { | |
1190 title = _("Move"); | |
1191 op_text = _("_Move"); | |
1192 if (fd) | |
1193 { | |
1194 text = _("Move file"); | |
1195 } | |
1196 else | |
1197 { | |
1198 text = _("Move multiple files"); | |
1199 } | |
1200 stock_id = GTK_STOCK_OK; | |
1201 } | |
1202 | |
1203 fdlg = file_util_file_dlg(title, GQ_WMCLASS, "dlg_copymove", parent, | |
1204 file_util_move_cancel_cb, NULL); | |
1205 generic_dialog_add_message(GENERIC_DIALOG(fdlg), NULL, text, NULL); | |
1206 | |
1207 if (fd) | |
1208 { | |
1209 GtkWidget *box; | |
1210 | |
1211 box = pref_box_new(GENERIC_DIALOG(fdlg)->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE); | |
1212 pref_label_new(box, _("File name:")); | |
1213 pref_label_new(box, fd->name); | |
1214 } | |
1215 | |
1216 label = pref_label_new(GENERIC_DIALOG(fdlg)->vbox, _("Choose the destination folder.")); | |
1217 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); | |
1218 pref_spacer(GENERIC_DIALOG(fdlg)->vbox, 0); | |
1219 | |
1220 file_dialog_add_button(fdlg, stock_id, op_text, file_util_move_cb, TRUE); | |
1221 | |
1222 file_dialog_add_path_widgets(fdlg, NULL, dest_path, "move_copy", NULL, NULL); | |
1223 | |
1224 fdlg->type = copy; | |
1225 fdlg->source_fd = fd; | |
1226 fdlg->source_list = source_list; | |
1227 fdlg->multiple_files = multiple; | |
1228 | |
1229 gtk_widget_show(GENERIC_DIALOG(fdlg)->dialog); | |
1230 } | |
1231 | |
1232 void file_util_move(FileData *source_fd, GList *source_list, const gchar *dest_path, GtkWidget *parent) | |
1233 { | |
1234 real_file_util_move(source_fd, source_list, dest_path, FALSE, parent); | |
1235 } | |
1236 | |
1237 void file_util_copy(FileData *source_fd, GList *source_list, const gchar *dest_path, GtkWidget *parent) | |
1238 { | |
1239 real_file_util_move(source_fd, source_list, dest_path, TRUE, parent); | |
1240 } | |
1241 | |
1242 void file_util_copy_path_to_clipboard(FileData *fd) | |
1243 { | |
1244 GtkClipboard *clipboard; | |
1245 | |
1246 if (!fd || !*fd->path) return; | |
1247 | |
1248 clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY); | |
1249 gtk_clipboard_set_text(clipboard, g_shell_quote(fd->path), -1); | |
1250 } | |
1251 | |
1252 void file_util_copy_path_list_to_clipboard(GList *list) | |
1253 { | |
1254 GtkClipboard *clipboard; | |
1255 GList *work; | |
1256 GString *new; | |
1257 | |
1258 clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY); | |
1259 | |
1260 new = g_string_new(""); | |
1261 work = list; | |
1262 while (work) { | |
1263 FileData *fd = work->data; | |
1264 work = work->next; | |
1265 | |
1266 if (!fd || !*fd->path) continue; | |
1267 | |
1268 g_string_append(new, g_shell_quote(fd->path)); | |
1269 if (work) g_string_append_c(new, ' '); | |
1270 } | |
1271 | |
1272 gtk_clipboard_set_text(clipboard, new->str, new->len); | |
1273 g_string_free(new, TRUE); | |
1274 } | |
1275 | |
1276 void file_util_move_simple(GList *list, const gchar *dest_path) | |
1277 { | |
1278 if (!list) return; | |
1279 if (!dest_path) | |
1280 { | |
1281 filelist_free(list); | |
1282 return; | |
1283 } | |
1284 | |
1285 if (!list->next) | |
1286 { | |
1287 FileData *source_fd; | |
1288 gchar *dest; | |
1289 | |
1290 source_fd = list->data; | |
1291 dest = g_build_filename(dest_path, source_fd->name, NULL); | |
1292 | |
1293 file_util_move_single(file_data_single_new(source_fd, dest, FALSE)); | |
1294 g_free(dest); | |
1295 filelist_free(list); | |
1296 return; | |
1297 } | |
1298 | |
1299 file_util_move_multiple(file_data_multiple_new(list, dest_path, FALSE)); | |
1300 } | |
1301 | |
1302 void file_util_copy_simple(GList *list, const gchar *dest_path) | |
1303 { | |
1304 if (!list) return; | |
1305 if (!dest_path) | |
1306 { | |
1307 filelist_free(list); | |
1308 return; | |
1309 } | |
1310 | |
1311 if (!list->next) | |
1312 { | |
1313 FileData *source_fd; | |
1314 gchar *dest; | |
1315 | |
1316 source_fd = list->data; | |
1317 dest = g_build_filename(dest_path, source_fd->name, NULL); | |
1318 | |
1319 file_util_move_single(file_data_single_new(source_fd, dest, TRUE)); | |
1320 g_free(dest); | |
1321 filelist_free(list); | |
1322 return; | |
1323 } | |
1324 | |
1325 file_util_move_multiple(file_data_multiple_new(list, dest_path, TRUE)); | |
1326 } | |
1327 | |
1328 | |
1329 | |
1330 /* | |
1331 *-------------------------------------------------------------------------- | |
1332 * Delete routines | |
1333 *-------------------------------------------------------------------------- | |
1334 */ | |
1335 | |
1336 static void box_append_safe_delete_status(GenericDialog *gd) | |
1337 { | |
1338 GtkWidget *label; | |
1339 gchar *buf; | |
1340 | |
1341 buf = file_util_safe_delete_status(); | |
1342 label = pref_label_new(gd->vbox, buf); | |
1343 g_free(buf); | |
1344 | |
1345 gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); | |
1346 gtk_widget_set_sensitive(label, FALSE); | |
1347 } | |
1348 | |
1349 | |
1350 static gint file_util_unlink(FileData *fd) | |
1351 { | |
1352 if (!isfile(fd->path)) return FALSE; | |
1353 | |
1354 | |
1355 if (!options->file_ops.safe_delete_enable) | |
1356 { | |
1357 return unlink_file(fd->path); | |
1358 } | |
1359 | |
1360 return file_util_safe_unlink(fd->path); | |
1361 } | |
1362 | |
1363 /* | |
1364 * delete multiple files | |
1365 */ | |
1366 | |
1367 static void file_util_delete_multiple_ok_cb(GenericDialog *gd, gpointer data); | |
1368 static void file_util_delete_multiple_cancel_cb(GenericDialog *gd, gpointer data); | |
1369 | |
1370 static void file_util_delete_ext_ok_cb(GenericDialog *gd, gpointer data) | |
1371 { | |
1372 editor_resume(data); | |
1373 } | |
1374 | |
1375 static void file_util_delete_ext_cancel_cb(GenericDialog *gd, gpointer data) | |
1376 { | |
1377 editor_skip(data); | |
1378 } | |
1379 | |
1380 | |
1381 static gint file_util_delete_ext_cb(gpointer resume_data, gint flags, GList *list, gpointer data) | |
1382 { | |
1383 gint ret = EDITOR_CB_CONTINUE; | 545 gint ret = EDITOR_CB_CONTINUE; |
1384 if ((flags & EDITOR_ERROR_MASK) && !(flags & EDITOR_ERROR_SKIPPED)) | 546 if ((flags & EDITOR_ERROR_MASK) && !(flags & EDITOR_ERROR_SKIPPED)) |
1385 { | 547 { |
1386 GString *msg = g_string_new(editor_get_error_str(flags)); | 548 GString *msg = g_string_new(editor_get_error_str(flags)); |
1387 g_string_append(msg,_("\nUnable to delete file by external command:\n")); | |
1388 GenericDialog *d; | 549 GenericDialog *d; |
550 g_string_append(msg, "\n"); | |
551 g_string_append(msg, ud->messages.fail); | |
552 g_string_append(msg, "\n"); | |
1389 while (list) | 553 while (list) |
1390 { | 554 { |
1391 FileData *fd = list->data; | 555 FileData *fd = list->data; |
1392 | 556 |
1393 g_string_append(msg, fd->path); | 557 g_string_append(msg, fd->path); |
1394 g_string_append(msg, "\n"); | 558 g_string_append(msg, "\n"); |
1395 list = list->next; | 559 list = list->next; |
1396 } | 560 } |
1397 if (resume_data) | 561 if (resume_data) |
1398 { | 562 { |
1399 g_string_append(msg, _("\n Continue multiple delete operation?")); | 563 g_string_append(msg, _("\n Continue multiple file operation?")); |
1400 d = file_util_gen_dlg(_("Delete failed"), GQ_WMCLASS, "dlg_confirm", | 564 d = file_util_gen_dlg(ud->messages.fail, GQ_WMCLASS, "dlg_confirm", |
1401 NULL, TRUE, | 565 NULL, TRUE, |
1402 file_util_delete_ext_cancel_cb, resume_data); | 566 file_util_abort_cb, ud); |
1403 | 567 |
1404 generic_dialog_add_message(d, GTK_STOCK_DIALOG_WARNING, NULL, msg->str); | 568 generic_dialog_add_message(d, GTK_STOCK_DIALOG_WARNING, NULL, msg->str); |
1405 | 569 |
1406 generic_dialog_add_button(d, GTK_STOCK_GO_FORWARD, _("Co_ntinue"), | 570 generic_dialog_add_button(d, GTK_STOCK_GO_FORWARD, _("Co_ntinue"), |
1407 file_util_delete_ext_ok_cb, TRUE); | 571 file_util_resume_cb, TRUE); |
1408 gtk_widget_show(d->dialog); | 572 gtk_widget_show(d->dialog); |
1409 ret = EDITOR_CB_SUSPEND; | 573 ret = EDITOR_CB_SUSPEND; |
1410 } | 574 } |
1411 else | 575 else |
1412 { | 576 { |
1413 file_util_warning_dialog(_("Delete failed"), msg->str, GTK_STOCK_DIALOG_ERROR, NULL); | 577 file_util_warning_dialog(ud->messages.fail, msg->str, GTK_STOCK_DIALOG_ERROR, NULL); |
1414 } | 578 } |
1415 g_string_free(msg, TRUE); | 579 g_string_free(msg, TRUE); |
1416 } | 580 } |
1417 | 581 |
1418 | 582 |
1419 { | 583 while (list) /* be careful, file_util_perform_ci_internal can pass ud->flist as list */ |
1420 while (list) | 584 { |
585 FileData *fd = list->data; | |
586 list = list->next; | |
587 | |
588 if (!(flags & EDITOR_ERROR_MASK)) /* files were successfully deleted, call the maint functions */ | |
589 file_data_sc_notify_ci(fd); | |
590 | |
591 ud->flist = g_list_remove(ud->flist, fd); | |
592 file_data_sc_free_ci(fd); | |
593 file_data_unref(fd); | |
594 } | |
595 | |
596 if (!resume_data) /* end of the list */ | |
597 { | |
598 ud->phase = UTILITY_PHASE_DONE; | |
599 file_util_dialog_run(ud); | |
600 } | |
601 | |
602 return ret; | |
603 } | |
604 | |
605 | |
606 /* | |
607 * perfirm the operation described by FileDataChangeInfo on all files in the list | |
608 * it is an alternative to start_editor_from_filelist_full, it should use similar interface | |
609 */ | |
610 | |
611 | |
612 void file_util_perform_ci_internal(UtilityData *ud) | |
613 { | |
614 | |
615 while (ud->flist) | |
616 { | |
617 gint ret; | |
618 | |
619 /* take a single entry each time, this allows better control over the operation */ | |
620 GList *single_entry = g_list_append(NULL, ud->flist->data); | |
621 gboolean last = !ud->flist->next; | |
622 | |
623 if (file_data_sc_perform_ci(single_entry->data)) | |
1421 { | 624 { |
1422 FileData *fd = list->data; | 625 ret = file_util_perform_ci_cb(GINT_TO_POINTER(!last), 0 /* OK */, single_entry, ud); |
1423 if (flags & EDITOR_ERROR_MASK) | |
1424 /* an error occured -> no change -> delete change info */ | |
1425 file_data_change_info_free(NULL, fd); | |
1426 else | |
1427 /* files were successfully deleted, call the maint functions and keep the change info forever */ | |
1428 file_maint_removed(fd, list); | |
1429 list = list->next; | |
1430 } | |
1431 } | |
1432 return ret; | |
1433 } | |
1434 | |
1435 static void file_util_delete_multiple_ok_cb(GenericDialog *gd, gpointer data) | |
1436 { | |
1437 GList *source_list = data; | |
1438 GList *work = source_list; | |
1439 gboolean ok = TRUE; | |
1440 | |
1441 while (work) | |
1442 { | |
1443 FileData *fd = work->data; | |
1444 if (fd->change) ok = FALSE; /* another operation in progress */ | |
1445 work = work->next; | |
1446 } | |
1447 | |
1448 if (!ok) | |
1449 { | |
1450 file_util_warning_dialog(_("File deletion failed"), _("Another operation in progress.\n"), GTK_STOCK_DIALOG_ERROR, NULL); | |
1451 filelist_free(source_list); | |
1452 return; | |
1453 } | |
1454 | |
1455 | |
1456 if (options->editor[CMD_DELETE].command) | |
1457 { | |
1458 gint flags; | |
1459 work = source_list; | |
1460 while (work) | |
1461 { | |
1462 FileData *fd = work->data; | |
1463 file_data_add_change_info(fd, FILEDATA_CHANGE_DELETE, NULL, NULL); | |
1464 work = work->next; | |
1465 } | |
1466 | |
1467 if ((flags = start_editor_from_filelist_full(CMD_DELETE, source_list, file_util_delete_ext_cb, NULL))) | |
1468 { | |
1469 gchar *text = g_strdup_printf(_("%s\nUnable to delete files by external command.\n"), editor_get_error_str(flags)); | |
1470 file_util_warning_dialog(_("File deletion failed"), text, GTK_STOCK_DIALOG_ERROR, NULL); | |
1471 g_free(text); | |
1472 } | |
1473 | |
1474 filelist_free(source_list); | |
1475 return; | |
1476 } | |
1477 | |
1478 | |
1479 while (source_list) | |
1480 { | |
1481 FileData *fd = source_list->data; | |
1482 | |
1483 source_list = g_list_remove(source_list, fd); | |
1484 | |
1485 if (!file_util_unlink(fd)) | |
1486 { | |
1487 if (source_list) | |
1488 { | |
1489 GenericDialog *d; | |
1490 gchar *text; | |
1491 | |
1492 d = file_util_gen_dlg(_("Delete failed"), GQ_WMCLASS, "dlg_confirm", | |
1493 NULL, TRUE, | |
1494 file_util_delete_multiple_cancel_cb, source_list); | |
1495 | |
1496 text = g_strdup_printf(_("Unable to delete file:\n %s\n Continue multiple delete operation?"), fd->path); | |
1497 generic_dialog_add_message(d, GTK_STOCK_DIALOG_WARNING, NULL, text); | |
1498 g_free(text); | |
1499 | |
1500 generic_dialog_add_button(d, GTK_STOCK_GO_FORWARD, _("Co_ntinue"), | |
1501 file_util_delete_multiple_ok_cb, TRUE); | |
1502 gtk_widget_show(d->dialog); | |
1503 } | |
1504 else | |
1505 { | |
1506 gchar *text; | |
1507 | |
1508 text = g_strdup_printf(_("Unable to delete file:\n%s"), fd->path); | |
1509 file_util_warning_dialog(_("Delete failed"), text, GTK_STOCK_DIALOG_ERROR, NULL); | |
1510 g_free(text); | |
1511 } | |
1512 file_data_unref(fd); | |
1513 return; | |
1514 } | 626 } |
1515 else | 627 else |
1516 { | 628 { |
1517 file_maint_removed(fd, source_list); | 629 ret = file_util_perform_ci_cb(GINT_TO_POINTER(!last), EDITOR_ERROR_STATUS, single_entry, ud); |
1518 } | 630 } |
1519 file_data_unref(fd); | 631 g_list_free(single_entry); |
1520 } | 632 |
1521 } | 633 if (ret == EDITOR_CB_SUSPEND || last) return; |
1522 | 634 |
1523 static void file_util_delete_multiple_cancel_cb(GenericDialog *gd, gpointer data) | 635 if (ret == EDITOR_CB_SKIP) |
1524 { | |
1525 GList *source_list = data; | |
1526 | |
1527 filelist_free(source_list); | |
1528 } | |
1529 | |
1530 static void file_util_delete_multiple_review_skip(GenericDialog *gd, gint next) | |
1531 { | |
1532 GtkWidget *button_back; | |
1533 GtkWidget *button_next; | |
1534 GtkWidget *button_label; | |
1535 GList *list; | |
1536 GList *list_point; | |
1537 FileData *fd; | |
1538 gchar *buf; | |
1539 | |
1540 list = gd->data; | |
1541 button_back = g_object_get_data(G_OBJECT(gd->dialog), "button_back"); | |
1542 button_next = g_object_get_data(G_OBJECT(gd->dialog), "button_next"); | |
1543 button_label = g_object_get_data(G_OBJECT(gd->dialog), "button_label"); | |
1544 list_point = g_object_get_data(G_OBJECT(gd->dialog), "list_point"); | |
1545 | |
1546 if (!list || !button_label) return; | |
1547 | |
1548 if (list_point) | |
1549 { | |
1550 if (next) | |
1551 { | 636 { |
1552 if (list_point->next) list_point = list_point->next; | 637 file_util_perform_ci_cb(NULL, EDITOR_ERROR_SKIPPED, ud->flist, ud); |
1553 } | 638 } |
1554 else | 639 |
640 /* FIXME: convert the loop to idle call */ | |
641 | |
642 } | |
643 } | |
644 | |
645 | |
646 void file_util_perform_ci(UtilityData *ud) | |
647 { | |
648 switch (ud->type) | |
649 { | |
650 case UTILITY_TYPE_COPY: | |
651 ud->external_command = CMD_COPY; | |
652 break; | |
653 case UTILITY_TYPE_MOVE: | |
654 ud->external_command = CMD_MOVE; | |
655 break; | |
656 case UTILITY_TYPE_RENAME: | |
657 ud->external_command = CMD_RENAME; | |
658 break; | |
659 case UTILITY_TYPE_DELETE: | |
660 case UTILITY_TYPE_DELETE_LINK: | |
661 case UTILITY_TYPE_DELETE_FOLDER: | |
662 ud->external_command = CMD_DELETE; | |
663 break; | |
664 case UTILITY_TYPE_FILTER: | |
665 case UTILITY_TYPE_EDITOR: | |
666 g_assert(ud->external_command != -1); /* it should be already set */ | |
667 break; | |
668 } | |
669 | |
670 if (ud->external_command != -1 && options->editor[ud->external_command].command) | |
671 { | |
672 gint flags; | |
673 ud->external = TRUE; | |
674 if ((flags = start_editor_from_filelist_full(ud->external_command, ud->flist, file_util_perform_ci_cb, ud))) | |
1555 { | 675 { |
1556 if (list_point->prev) list_point = list_point->prev; | 676 gchar *text = g_strdup_printf(_("%s\nUnable to start external command.\n"), editor_get_error_str(flags)); |
1557 } | 677 file_util_warning_dialog(ud->messages.fail, text, GTK_STOCK_DIALOG_ERROR, NULL); |
1558 } | |
1559 else | |
1560 { | |
1561 list_point = list; | |
1562 } | |
1563 | |
1564 if (!list_point) return; | |
1565 | |
1566 fd = list_point->data; | |
1567 buf = g_strdup_printf(_("File %d of %d"), | |
1568 g_list_index(list, (gpointer)fd) + 1, | |
1569 g_list_length(list)); | |
1570 gtk_label_set_text(GTK_LABEL(button_label), buf); | |
1571 g_free(buf); | |
1572 | |
1573 gtk_widget_set_sensitive(button_back, (list_point->prev != NULL) ); | |
1574 gtk_widget_set_sensitive(button_next, (list_point->next != NULL) ); | |
1575 | |
1576 generic_dialog_image_set(gd, fd); | |
1577 | |
1578 g_object_set_data(G_OBJECT(gd->dialog), "list_point", list_point); | |
1579 } | |
1580 | |
1581 static void file_util_delete_multiple_review_back(GtkWidget *button, gpointer data) | |
1582 { | |
1583 GenericDialog *gd = data; | |
1584 | |
1585 file_util_delete_multiple_review_skip(gd, FALSE); | |
1586 } | |
1587 | |
1588 static void file_util_delete_multiple_review_next(GtkWidget *button, gpointer data) | |
1589 { | |
1590 GenericDialog *gd = data; | |
1591 | |
1592 file_util_delete_multiple_review_skip(gd, TRUE); | |
1593 } | |
1594 | |
1595 static void file_util_delete_multiple_review_button_cb(ImageWindow *imd, gint button, guint32 time, | |
1596 gdouble x, gdouble y, guint state, gpointer data) | |
1597 { | |
1598 if (button == MOUSE_BUTTON_LEFT) | |
1599 { | |
1600 file_util_delete_multiple_review_next(NULL, data); | |
1601 } | |
1602 else if (button == MOUSE_BUTTON_MIDDLE || button == MOUSE_BUTTON_RIGHT) | |
1603 { | |
1604 file_util_delete_multiple_review_back(NULL, data); | |
1605 } | |
1606 } | |
1607 | |
1608 static void file_util_delete_multiple_review_scroll_cb(ImageWindow *imd, GdkScrollDirection direction, guint32 time, | |
1609 gdouble x, gdouble y, guint state, gpointer data) | |
1610 { | |
1611 if (direction == GDK_SCROLL_UP) | |
1612 { | |
1613 file_util_delete_multiple_review_back(NULL, data); | |
1614 } | |
1615 else if (direction == GDK_SCROLL_DOWN) | |
1616 { | |
1617 file_util_delete_multiple_review_next(NULL, data); | |
1618 } | |
1619 } | |
1620 | |
1621 static void file_util_delete_multiple(GList *source_list, GtkWidget *parent) | |
1622 { | |
1623 if (!options->file_ops.confirm_delete) | |
1624 { | |
1625 file_util_delete_multiple_ok_cb(NULL, source_list); | |
1626 } | |
1627 else | |
1628 { | |
1629 GenericDialog *gd; | |
1630 GtkWidget *hbox; | |
1631 GtkWidget *button; | |
1632 GtkWidget *label; | |
1633 ImageWindow *imd; | |
1634 gchar *buf; | |
1635 | |
1636 gd = file_util_gen_dlg(_("Delete files"), GQ_WMCLASS, "dlg_confirm", parent, TRUE, | |
1637 file_util_delete_multiple_cancel_cb, source_list); | |
1638 | |
1639 generic_dialog_add_message(gd, NULL, _("Delete multiple files"), NULL); | |
1640 | |
1641 generic_dialog_add_image(gd, NULL, NULL, NULL, NULL, NULL, TRUE); | |
1642 imd = g_object_get_data(G_OBJECT(gd->dialog), "img_image"); | |
1643 image_set_button_func(imd, file_util_delete_multiple_review_button_cb, gd); | |
1644 image_set_scroll_func(imd, file_util_delete_multiple_review_scroll_cb, gd); | |
1645 | |
1646 hbox = pref_box_new(gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP); | |
1647 | |
1648 button = pref_button_new(hbox, GTK_STOCK_GO_BACK, NULL, TRUE, | |
1649 G_CALLBACK(file_util_delete_multiple_review_back), gd); | |
1650 gtk_widget_set_sensitive(button, FALSE); | |
1651 g_object_set_data(G_OBJECT(gd->dialog), "button_back", button); | |
1652 | |
1653 button = pref_button_new(hbox, GTK_STOCK_GO_FORWARD, NULL, TRUE, | |
1654 G_CALLBACK(file_util_delete_multiple_review_next), gd); | |
1655 g_object_set_data(G_OBJECT(gd->dialog), "button_next", button); | |
1656 | |
1657 buf = g_strdup_printf(_("Review %d files"), g_list_length(source_list) ); | |
1658 label = pref_label_new(hbox, buf); | |
1659 g_free(buf); | |
1660 g_object_set_data(G_OBJECT(gd->dialog), "button_label", label); | |
1661 | |
1662 box_append_safe_delete_status(gd); | |
1663 | |
1664 generic_dialog_add_button(gd, GTK_STOCK_DELETE, NULL, file_util_delete_multiple_ok_cb, TRUE); | |
1665 | |
1666 gtk_widget_show(gd->dialog); | |
1667 } | |
1668 } | |
1669 | |
1670 /* | |
1671 * delete single file | |
1672 */ | |
1673 | |
1674 static void file_util_delete_ok_cb(GenericDialog *gd, gpointer data) | |
1675 { | |
1676 FileData *fd = data; | |
1677 | |
1678 if (!file_data_add_change_info(fd, FILEDATA_CHANGE_DELETE, NULL, NULL)) | |
1679 { | |
1680 file_util_warning_dialog(_("File deletion failed"), _("Another operation in progress.\n"), GTK_STOCK_DIALOG_ERROR, NULL); | |
1681 file_data_unref(fd); | |
1682 return; | |
1683 } | |
1684 | |
1685 | |
1686 if (options->editor[CMD_DELETE].command) | |
1687 { | |
1688 gint flags; | |
1689 if ((flags = start_editor_from_file_full(CMD_DELETE, fd, file_util_delete_ext_cb, NULL))) | |
1690 { | |
1691 gchar *text = g_strdup_printf(_("%s\nUnable to delete file by external command:\n%s"), editor_get_error_str(flags), fd->path); | |
1692 file_util_warning_dialog(_("File deletion failed"), text, GTK_STOCK_DIALOG_ERROR, NULL); | |
1693 g_free(text); | |
1694 file_data_change_info_free(NULL, fd); | |
1695 } | |
1696 } | |
1697 else if (!file_util_unlink(fd)) | |
1698 { | |
1699 gchar *text = g_strdup_printf(_("Unable to delete file:\n%s"), fd->path); | |
1700 file_util_warning_dialog(_("File deletion failed"), text, GTK_STOCK_DIALOG_ERROR, NULL); | |
1701 g_free(text); | |
1702 file_data_change_info_free(NULL, fd); | |
1703 } | |
1704 else | |
1705 { | |
1706 file_maint_removed(fd, NULL); | |
1707 } | |
1708 | |
1709 file_data_unref(fd); | |
1710 } | |
1711 | |
1712 static void file_util_delete_cancel_cb(GenericDialog *gd, gpointer data) | |
1713 { | |
1714 FileData *fd = data; | |
1715 | |
1716 file_data_unref(fd); | |
1717 } | |
1718 | |
1719 static void file_util_delete_single(FileData *fd, GtkWidget *parent) | |
1720 { | |
1721 if (!options->file_ops.confirm_delete) | |
1722 { | |
1723 file_util_delete_ok_cb(NULL, file_data_ref(fd)); | |
1724 } | |
1725 else | |
1726 { | |
1727 GenericDialog *gd; | |
1728 GtkWidget *table; | |
1729 gchar *base; | |
1730 | |
1731 gd = file_util_gen_dlg(_("Delete file"), GQ_WMCLASS, "dlg_confirm", parent, TRUE, | |
1732 file_util_delete_cancel_cb, file_data_ref(fd)); | |
1733 | |
1734 generic_dialog_add_message(gd, NULL, _("Delete file?"), NULL); | |
1735 | |
1736 table = pref_table_new(gd->vbox, 2, 2, FALSE, FALSE); | |
1737 | |
1738 pref_table_label(table, 0, 0, _("File name:"), 1.0); | |
1739 pref_table_label(table, 1, 0, fd->name, 0.0); | |
1740 | |
1741 pref_table_label(table, 0, 1, _("Location:"), 1.0); | |
1742 | |
1743 base = remove_level_from_path(fd->path); | |
1744 pref_table_label(table, 1, 1, base, 0.0); | |
1745 g_free(base); | |
1746 | |
1747 generic_dialog_add_image(gd, NULL, fd, NULL, NULL, NULL, FALSE); | |
1748 | |
1749 box_append_safe_delete_status(gd); | |
1750 | |
1751 generic_dialog_add_button(gd, GTK_STOCK_DELETE, NULL, file_util_delete_ok_cb, TRUE); | |
1752 | |
1753 gtk_widget_show(gd->dialog); | |
1754 } | |
1755 } | |
1756 | |
1757 void file_util_delete(FileData *source_fd, GList *source_list, GtkWidget *parent) | |
1758 { | |
1759 if (!source_fd && !source_list) return; | |
1760 | |
1761 if (source_fd) | |
1762 { | |
1763 file_util_delete_single(source_fd, parent); | |
1764 } | |
1765 else if (!source_list->next) | |
1766 { | |
1767 file_util_delete_single(source_list->data, parent); | |
1768 filelist_free(source_list); | |
1769 } | |
1770 else | |
1771 { | |
1772 file_util_delete_multiple(source_list, parent); | |
1773 } | |
1774 } | |
1775 | |
1776 /* | |
1777 *-------------------------------------------------------------------------- | |
1778 * Rename routines | |
1779 *-------------------------------------------------------------------------- | |
1780 */ | |
1781 | |
1782 /* | |
1783 * rename multiple files | |
1784 */ | |
1785 | |
1786 enum { | |
1787 RENAME_COLUMN_FD = 0, | |
1788 RENAME_COLUMN_PATH, | |
1789 RENAME_COLUMN_NAME, | |
1790 RENAME_COLUMN_PREVIEW, | |
1791 RENAME_COLUMN_COUNT | |
1792 }; | |
1793 | |
1794 typedef enum { | |
1795 RENAME_TYPE_MANUAL = 0, | |
1796 RENAME_TYPE_FORMATTED, | |
1797 RENAME_TYPE_AUTO | |
1798 } RenameType; | |
1799 | |
1800 typedef struct _RenameDataMult RenameDataMult; | |
1801 struct _RenameDataMult | |
1802 { | |
1803 FileDialog *fdlg; | |
1804 | |
1805 RenameType rename_type; | |
1806 | |
1807 GtkWidget *listview; | |
1808 GtkWidget *combo_type; | |
1809 | |
1810 GtkWidget *rename_box; | |
1811 GtkWidget *rename_label; | |
1812 GtkWidget *rename_entry; | |
1813 | |
1814 GtkWidget *auto_box; | |
1815 GtkWidget *auto_entry_front; | |
1816 GtkWidget *auto_spin_start; | |
1817 GtkWidget *auto_spin_pad; | |
1818 GtkWidget *auto_entry_end; | |
1819 | |
1820 GtkWidget *format_box; | |
1821 GtkWidget *format_entry; | |
1822 GtkWidget *format_spin; | |
1823 | |
1824 ImageWindow *imd; | |
1825 | |
1826 gint update_idle_id; | |
1827 }; | |
1828 | |
1829 static void file_util_rename_multiple(RenameDataMult *rd); | |
1830 | |
1831 static void file_util_rename_multiple_ok_cb(GenericDialog *gd, gpointer data) | |
1832 { | |
1833 RenameDataMult *rd = data; | |
1834 GtkWidget *dialog; | |
1835 | |
1836 dialog = GENERIC_DIALOG(rd->fdlg)->dialog; | |
1837 if (!GTK_WIDGET_VISIBLE(dialog)) gtk_widget_show(dialog); | |
1838 | |
1839 rd->fdlg->type = TRUE; | |
1840 file_util_rename_multiple(rd); | |
1841 } | |
1842 | |
1843 static void file_util_rename_multiple_cancel_cb(GenericDialog *gd, gpointer data) | |
1844 { | |
1845 RenameDataMult *rd = data; | |
1846 GtkWidget *dialog; | |
1847 | |
1848 dialog = GENERIC_DIALOG(rd->fdlg)->dialog; | |
1849 if (!GTK_WIDGET_VISIBLE(dialog)) gtk_widget_show(dialog); | |
1850 } | |
1851 | |
1852 static gint file_util_rename_multiple_find_row(RenameDataMult *rd, FileData *fd, GtkTreeIter *iter) | |
1853 { | |
1854 GtkTreeModel *store; | |
1855 gint valid; | |
1856 gint row = 0; | |
1857 | |
1858 store = gtk_tree_view_get_model(GTK_TREE_VIEW(rd->listview)); | |
1859 valid = gtk_tree_model_get_iter_first(store, iter); | |
1860 while (valid) | |
1861 { | |
1862 FileData *fd_n; | |
1863 gint ret; | |
1864 | |
1865 gtk_tree_model_get(GTK_TREE_MODEL(store), iter, RENAME_COLUMN_FD, &fd_n, -1); | |
1866 ret = (fd_n == fd); | |
1867 // file_data_unref(fd_n); | |
1868 if (ret) return row; | |
1869 | |
1870 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), iter); | |
1871 row++; | |
1872 } | |
1873 | |
1874 return -1; | |
1875 } | |
1876 | |
1877 static void file_util_rename_multiple(RenameDataMult *rd) | |
1878 { | |
1879 FileDialog *fdlg; | |
1880 | |
1881 fdlg = rd->fdlg; | |
1882 | |
1883 if (isfile(fdlg->dest_path) && !fdlg->type) | |
1884 { | |
1885 GenericDialog *gd; | |
1886 | |
1887 gd = file_util_gen_dlg(_("Overwrite file"), GQ_WMCLASS, "dlg_confirm", | |
1888 NULL, TRUE, | |
1889 file_util_rename_multiple_cancel_cb, rd); | |
1890 | |
1891 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, | |
1892 _("Overwrite file?"), | |
1893 _("Replace existing file by renaming new file.")); | |
1894 pref_spacer(gd->vbox, 0); | |
1895 | |
1896 generic_dialog_add_button(gd, GTK_STOCK_OK, _("_Overwrite"), file_util_rename_multiple_ok_cb, TRUE); | |
1897 generic_dialog_add_image(gd, NULL, | |
1898 file_data_new_simple(fdlg->dest_path), _("Existing file"), | |
1899 fdlg->source_fd, _("New file"), TRUE); | |
1900 | |
1901 gtk_widget_hide(GENERIC_DIALOG(fdlg)->dialog); | |
1902 | |
1903 gtk_widget_show(gd->dialog); | |
1904 return; | |
1905 } | |
1906 else | |
1907 { | |
1908 if (!file_data_add_change_info(fdlg->source_fd, FILEDATA_CHANGE_RENAME, fdlg->source_fd->path, fdlg->dest_path) || | |
1909 !rename_file_ext(fdlg->source_fd)) | |
1910 { | |
1911 gchar *text = g_strdup_printf(_("Unable to rename file:\n%s\n to:\n%s"), | |
1912 fdlg->source_fd->name, | |
1913 filename_from_path(fdlg->dest_path)); | |
1914 file_util_warning_dialog(_("Error renaming file"), text, GTK_STOCK_DIALOG_ERROR, NULL); | |
1915 g_free(text); | 678 g_free(text); |
1916 } | 679 } |
1917 else | 680 } |
1918 { | 681 else |
1919 GtkTreeModel *store; | 682 { |
1920 GtkTreeIter iter; | 683 ud->external = FALSE; |
1921 GtkTreeIter next; | 684 file_util_perform_ci_internal(ud); |
1922 gint row; | 685 } |
1923 | 686 } |
1924 store = gtk_tree_view_get_model(GTK_TREE_VIEW(rd->listview)); | 687 |
1925 row = file_util_rename_multiple_find_row(rd, rd->fdlg->source_fd, &iter); | 688 |
1926 | 689 |
1927 if (row >= 0 && | 690 |
1928 (gtk_tree_model_iter_nth_child(store, &next, NULL, row + 1) || | 691 static void file_util_cancel_cb(GenericDialog *gd, gpointer data) |
1929 (row > 0 && gtk_tree_model_iter_nth_child(store, &next, NULL, row - 1)) ) ) | 692 { |
1930 { | 693 UtilityData *ud = data; |
1931 GtkTreeSelection *selection; | 694 |
1932 | 695 generic_dialog_close(gd); |
1933 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(rd->listview)); | 696 |
1934 gtk_tree_selection_select_iter(selection, &next); | 697 ud->gd = NULL; |
1935 gtk_list_store_remove(GTK_LIST_STORE(store), &iter); | 698 |
1936 } | 699 ud->phase = UTILITY_PHASE_CANCEL; |
1937 else | 700 file_util_dialog_run(ud); |
1938 { | 701 } |
1939 DEBUG_1("closed by #%d", row); | 702 |
1940 | 703 static void file_util_ok_cb(GenericDialog *gd, gpointer data) |
1941 file_dialog_close(rd->fdlg); | 704 { |
1942 } | 705 UtilityData *ud = data; |
1943 } | 706 |
1944 } | 707 generic_dialog_close(gd); |
1945 } | 708 |
709 ud->gd = NULL; | |
710 | |
711 file_util_dialog_run(ud); | |
712 } | |
713 | |
714 static void file_util_fdlg_cancel_cb(FileDialog *fdlg, gpointer data) | |
715 { | |
716 UtilityData *ud = data; | |
717 | |
718 file_dialog_close(fdlg); | |
719 | |
720 ud->fdlg = NULL; | |
721 | |
722 ud->phase = UTILITY_PHASE_CANCEL; | |
723 file_util_dialog_run(ud); | |
724 } | |
725 | |
726 static void file_util_fdlg_ok_cb(FileDialog *fdlg, gpointer data) | |
727 { | |
728 UtilityData *ud = data; | |
729 | |
730 file_dialog_close(fdlg); | |
731 | |
732 ud->fdlg = NULL; | |
733 | |
734 file_util_dialog_run(ud); | |
735 } | |
736 | |
737 | |
738 static void file_util_dest_folder_entry_cb(GtkWidget *entry, gpointer data) | |
739 { | |
740 UtilityData *ud = data; | |
741 | |
742 g_free(ud->dest_path); | |
743 ud->dest_path = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry))); | |
744 | |
745 switch (ud->type) | |
746 { | |
747 case UTILITY_TYPE_COPY: | |
748 file_data_sc_update_ci_copy_list(ud->flist, ud->dest_path); | |
749 break; | |
750 case UTILITY_TYPE_MOVE: | |
751 file_data_sc_update_ci_move_list(ud->flist, ud->dest_path); | |
752 break; | |
753 case UTILITY_TYPE_FILTER: | |
754 case UTILITY_TYPE_EDITOR: | |
755 file_data_sc_update_ci_unspecified_list(ud->flist, ud->dest_path); | |
756 break; | |
757 case UTILITY_TYPE_DELETE: | |
758 case UTILITY_TYPE_DELETE_LINK: | |
759 case UTILITY_TYPE_DELETE_FOLDER: | |
760 case UTILITY_TYPE_RENAME: | |
761 g_warning("unhandled operation"); | |
762 } | |
763 } | |
764 | |
1946 | 765 |
1947 /* format: * = filename without extension, ## = number position, extension is kept */ | 766 /* format: * = filename without extension, ## = number position, extension is kept */ |
1948 static gchar *file_util_rename_multiple_auto_format_name(const gchar *format, const gchar *name, gint n) | 767 static gchar *file_util_rename_multiple_auto_format_name(const gchar *format, const gchar *name, gint n) |
1949 { | 768 { |
1950 gchar *new_name; | 769 gchar *new_name; |
2001 g_free(parsed); | 820 g_free(parsed); |
2002 | 821 |
2003 return new_name; | 822 return new_name; |
2004 } | 823 } |
2005 | 824 |
2006 static void file_util_rename_multiple_auto(RenameDataMult *rd) | 825 |
2007 { | 826 static void file_util_rename_preview_update(UtilityData *ud) |
2008 const gchar *front; | 827 { |
2009 const gchar *end; | |
2010 const gchar *format; | |
2011 gint start_n; | |
2012 gint padding; | |
2013 gint n; | |
2014 GtkTreeModel *store; | 828 GtkTreeModel *store; |
2015 GtkTreeIter iter; | 829 GtkTreeSelection *selection; |
2016 gint valid; | |
2017 gint success; | |
2018 | |
2019 front = gtk_entry_get_text(GTK_ENTRY(rd->auto_entry_front)); | |
2020 end = gtk_entry_get_text(GTK_ENTRY(rd->auto_entry_end)); | |
2021 padding = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(rd->auto_spin_pad)); | |
2022 | |
2023 format = gtk_entry_get_text(GTK_ENTRY(rd->format_entry)); | |
2024 | |
2025 if (rd->rename_type == RENAME_TYPE_FORMATTED) | |
2026 { | |
2027 start_n = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(rd->format_spin)); | |
2028 | |
2029 if (!format || | |
2030 (strchr(format, '*') == NULL && strchr(format, '#') == NULL)) | |
2031 { | |
2032 file_util_warning_dialog(_("Auto rename"), | |
2033 _("Format must include at least one of the symbol characters '*' or '#'.\n"), | |
2034 GTK_STOCK_DIALOG_WARNING, NULL); | |
2035 return; | |
2036 } | |
2037 | |
2038 history_combo_append_history(rd->format_entry, NULL); | |
2039 } | |
2040 else | |
2041 { | |
2042 start_n = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(rd->auto_spin_start)); | |
2043 | |
2044 history_combo_append_history(rd->auto_entry_front, NULL); | |
2045 history_combo_append_history(rd->auto_entry_end, NULL); | |
2046 } | |
2047 | |
2048 store = gtk_tree_view_get_model(GTK_TREE_VIEW(rd->listview)); | |
2049 | |
2050 /* first check for name conflicts */ | |
2051 success = TRUE; | |
2052 n = start_n; | |
2053 valid = gtk_tree_model_get_iter_first(store, &iter); | |
2054 while (valid && success) | |
2055 { | |
2056 gchar *dest; | |
2057 gchar *base; | |
2058 FileData *fd; | |
2059 | |
2060 gtk_tree_model_get(store, &iter, RENAME_COLUMN_FD, &fd, -1); | |
2061 base = remove_level_from_path(fd->path); | |
2062 | |
2063 if (rd->rename_type == RENAME_TYPE_FORMATTED) | |
2064 { | |
2065 gchar *new_name; | |
2066 | |
2067 new_name = file_util_rename_multiple_auto_format_name(format, fd->name, n); | |
2068 dest = g_build_filename(base, new_name, NULL); | |
2069 g_free(new_name); | |
2070 } | |
2071 else | |
2072 { | |
2073 gchar *new_name; | |
2074 | |
2075 new_name = g_strdup_printf("%s%0*d%s", front, padding, n, end); | |
2076 dest = g_build_filename(base, new_name, NULL); | |
2077 g_free(new_name); | |
2078 } | |
2079 | |
2080 if (isname(dest)) success = FALSE; | |
2081 | |
2082 g_free(dest); | |
2083 g_free(base); | |
2084 // file_data_unref(fd); | |
2085 | |
2086 n++; | |
2087 valid = gtk_tree_model_iter_next(store, &iter); | |
2088 } | |
2089 | |
2090 if (!success) | |
2091 { | |
2092 file_util_warning_dialog(_("Auto rename"), | |
2093 _("Can not auto rename with the selected\nnumber set, one or more files exist that\nmatch the resulting name list.\n"), | |
2094 GTK_STOCK_DIALOG_WARNING, NULL); | |
2095 return; | |
2096 } | |
2097 | |
2098 /* select the first iter, so that on fail the correct info is given to user */ | |
2099 if (gtk_tree_model_get_iter_first(store, &iter)) | |
2100 { | |
2101 GtkTreeSelection *selection; | |
2102 | |
2103 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(rd->listview)); | |
2104 gtk_tree_selection_select_iter(selection, &iter); | |
2105 } | |
2106 | |
2107 /* now do it for real */ | |
2108 success = TRUE; | |
2109 n = start_n; | |
2110 while (success && gtk_tree_model_get_iter_first(store, &iter)) | |
2111 { | |
2112 gchar *dest; | |
2113 gchar *base; | |
2114 FileData *fd; | |
2115 | |
2116 gtk_tree_model_get(store, &iter, RENAME_COLUMN_FD, &fd, -1); | |
2117 base = remove_level_from_path(fd->path); | |
2118 | |
2119 if (rd->rename_type == RENAME_TYPE_FORMATTED) | |
2120 { | |
2121 gchar *new_name; | |
2122 | |
2123 new_name = file_util_rename_multiple_auto_format_name(format, fd->name, n); | |
2124 dest = g_build_filename(base, new_name, NULL); | |
2125 g_free(new_name); | |
2126 } | |
2127 else | |
2128 { | |
2129 gchar *new_name; | |
2130 | |
2131 new_name = g_strdup_printf("%s%0*d%s", front, padding, n, end); | |
2132 dest = g_build_filename(base, new_name, NULL); | |
2133 g_free(new_name); | |
2134 } | |
2135 | |
2136 if (!file_data_add_change_info(fd, FILEDATA_CHANGE_RENAME, fd->path, dest) || | |
2137 !rename_file_ext(fd)) | |
2138 { | |
2139 success = FALSE; | |
2140 } | |
2141 | |
2142 g_free(dest); | |
2143 g_free(base); | |
2144 // file_data_unref(fd); | |
2145 | |
2146 if (success) | |
2147 { | |
2148 gtk_list_store_remove(GTK_LIST_STORE(store), &iter); | |
2149 if (gtk_tree_model_get_iter_first(store, &iter)) | |
2150 { | |
2151 GtkTreeSelection *selection; | |
2152 | |
2153 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(rd->listview)); | |
2154 gtk_tree_selection_select_iter(selection, &iter); | |
2155 } | |
2156 } | |
2157 | |
2158 n++; | |
2159 } | |
2160 | |
2161 if (!success) | |
2162 { | |
2163 gchar *buf; | |
2164 | |
2165 n--; | |
2166 gtk_spin_button_set_value(GTK_SPIN_BUTTON(rd->auto_spin_start), (gdouble)n); | |
2167 | |
2168 buf = g_strdup_printf(_("Failed to rename\n%s\nThe number was %d."), rd->fdlg->source_fd->name, n); | |
2169 file_util_warning_dialog(_("Auto rename"), buf, GTK_STOCK_DIALOG_ERROR, NULL); | |
2170 g_free(buf); | |
2171 | |
2172 return; | |
2173 } | |
2174 | |
2175 file_dialog_close(rd->fdlg); | |
2176 } | |
2177 | |
2178 static void file_util_rename_multiple_cb(FileDialog *fdlg, gpointer data) | |
2179 { | |
2180 RenameDataMult *rd = data; | |
2181 gchar *base; | |
2182 const gchar *name; | |
2183 | |
2184 if (rd->rename_type != RENAME_TYPE_MANUAL) | |
2185 { | |
2186 file_util_rename_multiple_auto(rd); | |
2187 return; | |
2188 } | |
2189 | |
2190 name = gtk_entry_get_text(GTK_ENTRY(rd->rename_entry)); | |
2191 base = remove_level_from_path(fdlg->source_fd->path); | |
2192 | |
2193 g_free(fdlg->dest_path); | |
2194 fdlg->dest_path = g_build_filename(base, name, NULL); | |
2195 g_free(base); | |
2196 | |
2197 if (strlen(name) == 0 || strcmp(fdlg->source_fd->path, fdlg->dest_path) == 0) | |
2198 { | |
2199 return; | |
2200 } | |
2201 | |
2202 fdlg->type = FALSE; | |
2203 file_util_rename_multiple(rd); | |
2204 } | |
2205 | |
2206 static void file_util_rename_multiple_close_cb(FileDialog *fdlg, gpointer data) | |
2207 { | |
2208 RenameDataMult *rd = data; | |
2209 | |
2210 file_dialog_close(rd->fdlg); | |
2211 } | |
2212 | |
2213 static gboolean file_util_rename_multiple_select_cb(GtkTreeSelection *selection, GtkTreeModel *store, GtkTreePath *tpath, | |
2214 gboolean path_currently_selected, gpointer data) | |
2215 { | |
2216 RenameDataMult *rd = data; | |
2217 GtkTreeIter iter; | |
2218 const gchar *name; | |
2219 FileData *fd = NULL; | |
2220 | |
2221 if (path_currently_selected || | |
2222 !gtk_tree_model_get_iter(store, &iter, tpath)) return TRUE; | |
2223 gtk_tree_model_get(store, &iter, RENAME_COLUMN_FD, &fd, -1); | |
2224 | |
2225 file_data_unref(rd->fdlg->source_fd); | |
2226 rd->fdlg->source_fd = file_data_ref(fd); | |
2227 | |
2228 name = rd->fdlg->source_fd->name; | |
2229 gtk_label_set_text(GTK_LABEL(rd->rename_label), name); | |
2230 gtk_entry_set_text(GTK_ENTRY(rd->rename_entry), name); | |
2231 | |
2232 image_change_fd(rd->imd, rd->fdlg->source_fd, 0.0); | |
2233 | |
2234 if (GTK_WIDGET_VISIBLE(rd->rename_box)) | |
2235 { | |
2236 gtk_widget_grab_focus(rd->rename_entry); | |
2237 gtk_editable_select_region(GTK_EDITABLE(rd->rename_entry), 0, filename_base_length(name)); | |
2238 } | |
2239 | |
2240 return TRUE; | |
2241 } | |
2242 | |
2243 static void file_util_rename_multiple_preview_update(RenameDataMult *rd) | |
2244 { | |
2245 GtkTreeModel *store; | |
2246 GtkTreeIter iter; | 830 GtkTreeIter iter; |
2247 const gchar *front; | 831 const gchar *front; |
2248 const gchar *end; | 832 const gchar *end; |
2249 const gchar *format; | 833 const gchar *format; |
2250 gint valid; | 834 gint valid; |
2251 gint start_n; | 835 gint start_n; |
2252 gint padding; | 836 gint padding; |
2253 gint n; | 837 gint n; |
2254 | 838 gint mode; |
2255 front = gtk_entry_get_text(GTK_ENTRY(rd->auto_entry_front)); | 839 |
2256 end = gtk_entry_get_text(GTK_ENTRY(rd->auto_entry_end)); | 840 mode = gtk_notebook_get_current_page(GTK_NOTEBOOK(ud->notebook)); |
2257 padding = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(rd->auto_spin_pad)); | 841 |
2258 | 842 if (mode == UTILITY_RENAME) |
2259 format = gtk_entry_get_text(GTK_ENTRY(rd->format_entry)); | 843 { |
2260 | 844 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ud->listview)); |
2261 if (rd->rename_type == RENAME_TYPE_FORMATTED) | 845 if (gtk_tree_selection_get_selected(selection, &store, &iter)) |
2262 { | 846 { |
2263 start_n = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(rd->format_spin)); | 847 FileData *fd; |
848 const gchar *dest = gtk_entry_get_text(GTK_ENTRY(ud->rename_entry)); | |
849 | |
850 gtk_tree_model_get(store, &iter, UTILITY_COLUMN_FD, &fd, -1); | |
851 file_data_sc_update_ci_rename(fd, dest); | |
852 gtk_list_store_set(GTK_LIST_STORE(store), &iter, | |
853 UTILITY_COLUMN_DEST_PATH, fd->change->dest, | |
854 UTILITY_COLUMN_DEST_NAME, filename_from_path(fd->change->dest), | |
855 -1); | |
856 } | |
857 return; | |
858 } | |
859 | |
860 | |
861 front = gtk_entry_get_text(GTK_ENTRY(ud->auto_entry_front)); | |
862 end = gtk_entry_get_text(GTK_ENTRY(ud->auto_entry_end)); | |
863 padding = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ud->auto_spin_pad)); | |
864 | |
865 format = gtk_entry_get_text(GTK_ENTRY(ud->format_entry)); | |
866 | |
867 if (mode == UTILITY_RENAME_FORMATTED) | |
868 { | |
869 start_n = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ud->format_spin)); | |
2264 } | 870 } |
2265 else | 871 else |
2266 { | 872 { |
2267 start_n = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(rd->auto_spin_start)); | 873 start_n = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ud->auto_spin_start)); |
2268 } | 874 } |
2269 | 875 |
2270 store = gtk_tree_view_get_model(GTK_TREE_VIEW(rd->listview)); | 876 store = gtk_tree_view_get_model(GTK_TREE_VIEW(ud->listview)); |
2271 n = start_n; | 877 n = start_n; |
2272 valid = gtk_tree_model_get_iter_first(store, &iter); | 878 valid = gtk_tree_model_get_iter_first(store, &iter); |
2273 while (valid) | 879 while (valid) |
2274 { | 880 { |
2275 gchar *dest; | 881 gchar *dest; |
2276 | 882 FileData *fd; |
2277 if (rd->rename_type == RENAME_TYPE_FORMATTED) | 883 gtk_tree_model_get(store, &iter, UTILITY_COLUMN_FD, &fd, -1); |
884 | |
885 if (mode == UTILITY_RENAME_FORMATTED) | |
2278 { | 886 { |
2279 FileData *fd; | |
2280 | |
2281 gtk_tree_model_get(store, &iter, RENAME_COLUMN_FD, &fd, -1); | |
2282 dest = file_util_rename_multiple_auto_format_name(format, fd->name, n); | 887 dest = file_util_rename_multiple_auto_format_name(format, fd->name, n); |
2283 // file_data_unref(fd); | |
2284 } | 888 } |
2285 else | 889 else |
2286 { | 890 { |
2287 dest = g_strdup_printf("%s%0*d%s", front, padding, n, end); | 891 dest = g_strdup_printf("%s%0*d%s", front, padding, n, end); |
2288 } | 892 } |
2289 gtk_list_store_set(GTK_LIST_STORE(store), &iter, RENAME_COLUMN_PREVIEW, dest, -1); | 893 |
894 file_data_sc_update_ci_rename(fd, dest); | |
895 gtk_list_store_set(GTK_LIST_STORE(store), &iter, | |
896 UTILITY_COLUMN_DEST_PATH, fd->change->dest, | |
897 UTILITY_COLUMN_DEST_NAME, filename_from_path(fd->change->dest), | |
898 -1); | |
2290 g_free(dest); | 899 g_free(dest); |
2291 | 900 |
2292 n++; | 901 n++; |
2293 valid = gtk_tree_model_iter_next(store, &iter); | 902 valid = gtk_tree_model_iter_next(store, &iter); |
2294 } | 903 } |
2295 | 904 |
2296 } | 905 } |
2297 | 906 |
2298 static gboolean file_util_rename_multiple_idle_cb(gpointer data) | 907 static void file_util_rename_preview_entry_cb(GtkWidget *entry, gpointer data) |
2299 { | 908 { |
2300 RenameDataMult *rd = data; | 909 UtilityData *ud = data; |
2301 | 910 file_util_rename_preview_update(ud); |
2302 file_util_rename_multiple_preview_update(rd); | 911 } |
2303 | 912 |
2304 rd->update_idle_id = -1; | 913 static void file_util_rename_preview_adj_cb(GtkWidget *spin, gpointer data) |
914 { | |
915 UtilityData *ud = data; | |
916 file_util_rename_preview_update(ud); | |
917 } | |
918 | |
919 static gboolean file_util_rename_idle_cb(gpointer data) | |
920 { | |
921 UtilityData *ud = data; | |
922 | |
923 file_util_rename_preview_update(ud); | |
924 | |
925 ud->update_idle_id = -1; | |
2305 return FALSE; | 926 return FALSE; |
2306 } | 927 } |
2307 | 928 |
2308 static void file_util_rename_multiple_preview_order_cb(GtkTreeModel *treemodel, GtkTreePath *tpath, | 929 static void file_util_rename_preview_order_cb(GtkTreeModel *treemodel, GtkTreePath *tpath, |
2309 GtkTreeIter *iter, gpointer data) | 930 GtkTreeIter *iter, gpointer data) |
2310 { | 931 { |
2311 RenameDataMult *rd = data; | 932 UtilityData *ud = data; |
2312 | 933 |
2313 if (rd->rename_type != RENAME_TYPE_MANUAL && rd->update_idle_id == -1) | 934 if (ud->update_idle_id == -1) |
2314 { | 935 { |
2315 rd->update_idle_id = g_idle_add(file_util_rename_multiple_idle_cb, rd); | 936 ud->update_idle_id = g_idle_add(file_util_rename_idle_cb, ud); |
2316 } | 937 } |
2317 } | 938 } |
2318 | 939 |
2319 static void file_util_rename_multiple_preview_entry_cb(GtkWidget *entry, gpointer data) | 940 |
2320 { | 941 static gboolean file_util_preview_cb(GtkTreeSelection *selection, GtkTreeModel *store, |
2321 RenameDataMult *rd = data; | 942 GtkTreePath *tpath, gboolean path_currently_selected, |
2322 file_util_rename_multiple_preview_update(rd); | 943 gpointer data) |
2323 } | 944 { |
2324 | 945 UtilityData *ud = data; |
2325 static void file_util_rename_multiple_preview_adj_cb(GtkWidget *spin, gpointer data) | 946 GtkTreeIter iter; |
2326 { | 947 FileData *fd = NULL; |
2327 RenameDataMult *rd = data; | 948 |
2328 file_util_rename_multiple_preview_update(rd); | 949 if (path_currently_selected || |
2329 } | 950 !gtk_tree_model_get_iter(store, &iter, tpath)) return TRUE; |
2330 | 951 |
2331 static void file_util_rename_multiple_auto_change(GtkWidget *widget, gpointer data) | 952 gtk_tree_model_get(store, &iter, UTILITY_COLUMN_FD, &fd, -1); |
2332 { | 953 generic_dialog_image_set(ud->gd, fd); |
2333 RenameDataMult *rd = data; | 954 |
2334 GtkTreeViewColumn *column; | 955 if (ud->type == UTILITY_TYPE_RENAME) |
2335 | 956 { |
2336 rd->rename_type = gtk_combo_box_get_active(GTK_COMBO_BOX(rd->combo_type)); | 957 const gchar *name = filename_from_path(fd->change->dest); |
2337 | 958 gtk_widget_grab_focus(ud->rename_entry); |
2338 switch (rd->rename_type) | 959 gtk_label_set_text(GTK_LABEL(ud->rename_label), fd->name); |
2339 { | 960 g_signal_handlers_block_by_func(ud->rename_entry, G_CALLBACK(file_util_rename_preview_entry_cb), ud); |
2340 case RENAME_TYPE_FORMATTED: | 961 gtk_entry_set_text(GTK_ENTRY(ud->rename_entry), name); |
2341 if (GTK_WIDGET_VISIBLE(rd->rename_box)) gtk_widget_hide(rd->rename_box); | 962 gtk_editable_select_region(GTK_EDITABLE(ud->rename_entry), 0, filename_base_length(name)); |
2342 if (GTK_WIDGET_VISIBLE(rd->auto_box)) gtk_widget_hide(rd->auto_box); | 963 g_signal_handlers_unblock_by_func(ud->rename_entry, G_CALLBACK(file_util_rename_preview_entry_cb), ud); |
2343 if (!GTK_WIDGET_VISIBLE(rd->format_box)) gtk_widget_show(rd->format_box); | 964 } |
2344 file_util_rename_multiple_preview_update(rd); | 965 |
2345 break; | 966 return TRUE; |
2346 case RENAME_TYPE_AUTO: | 967 } |
2347 if (GTK_WIDGET_VISIBLE(rd->format_box)) gtk_widget_hide(rd->format_box); | 968 |
2348 if (GTK_WIDGET_VISIBLE(rd->rename_box)) gtk_widget_hide(rd->rename_box); | 969 |
2349 if (!GTK_WIDGET_VISIBLE(rd->auto_box)) gtk_widget_show(rd->auto_box); | 970 |
2350 file_util_rename_multiple_preview_update(rd); | 971 static void box_append_safe_delete_status(GenericDialog *gd) |
2351 break; | 972 { |
2352 case RENAME_TYPE_MANUAL: | 973 GtkWidget *label; |
2353 default: | 974 gchar *buf; |
2354 if (GTK_WIDGET_VISIBLE(rd->format_box)) gtk_widget_hide(rd->format_box); | 975 |
2355 if (GTK_WIDGET_VISIBLE(rd->auto_box)) gtk_widget_hide(rd->auto_box); | 976 buf = file_util_safe_delete_status(); |
2356 if (!GTK_WIDGET_VISIBLE(rd->rename_box)) gtk_widget_show(rd->rename_box); | 977 label = pref_label_new(gd->vbox, buf); |
2357 break; | 978 g_free(buf); |
2358 } | 979 |
2359 | 980 gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); |
2360 column = gtk_tree_view_get_column(GTK_TREE_VIEW(rd->listview), RENAME_COLUMN_PREVIEW - 1); | 981 gtk_widget_set_sensitive(label, FALSE); |
2361 gtk_tree_view_column_set_visible(column, (rd->rename_type != RENAME_TYPE_MANUAL)); | 982 } |
2362 } | 983 |
984 | |
985 static void file_util_dialog_init_simple_list(UtilityData *ud) | |
986 { | |
987 GtkWidget *box; | |
988 GtkTreeSelection *selection; | |
989 ud->gd = file_util_gen_dlg(ud->messages.title, GQ_WMCLASS, "dlg_confirm", | |
990 ud->parent, FALSE, file_util_cancel_cb, ud); | |
991 generic_dialog_add_button(ud->gd, GTK_STOCK_DELETE, NULL, file_util_ok_cb, TRUE); | |
992 | |
993 box = generic_dialog_add_message(ud->gd, GTK_STOCK_DIALOG_QUESTION, | |
994 ud->messages.question, | |
995 ud->messages.desc_flist); | |
996 | |
997 box = pref_group_new(box, TRUE, ud->messages.desc_flist, GTK_ORIENTATION_HORIZONTAL); | |
998 | |
999 ud->listview = file_util_dialog_add_list(box, ud->flist, FALSE); | |
1000 file_util_dialog_add_list_column(ud->listview, _("Sidecars"), UTILITY_COLUMN_SIDECARS); | |
1001 | |
1002 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ud->listview)); | |
1003 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); | |
1004 gtk_tree_selection_set_select_function(selection, file_util_preview_cb, ud, NULL); | |
1005 | |
1006 generic_dialog_add_image(ud->gd, box, NULL, NULL, NULL, NULL, FALSE); | |
1007 | |
1008 box_append_safe_delete_status(ud->gd); | |
1009 | |
1010 gtk_widget_show(ud->gd->dialog); | |
1011 | |
1012 file_util_dialog_list_select(ud->listview, 0); | |
1013 } | |
1014 | |
1015 static void file_util_dialog_init_dest_folder(UtilityData *ud) | |
1016 { | |
1017 FileDialog *fdlg; | |
1018 GtkWidget *label; | |
1019 const gchar *stock_id; | |
1020 | |
1021 if (ud->type == UTILITY_TYPE_COPY) | |
1022 { | |
1023 stock_id = GTK_STOCK_COPY; | |
1024 } | |
1025 else | |
1026 { | |
1027 stock_id = GTK_STOCK_OK; | |
1028 } | |
1029 | |
1030 fdlg = file_util_file_dlg(ud->messages.title, GQ_WMCLASS, "dlg_dest_folder", ud->parent, | |
1031 file_util_fdlg_cancel_cb, ud); | |
1032 | |
1033 ud->fdlg = fdlg; | |
1034 | |
1035 generic_dialog_add_message(GENERIC_DIALOG(fdlg), NULL, ud->messages.question, NULL); | |
1036 | |
1037 label = pref_label_new(GENERIC_DIALOG(fdlg)->vbox, _("Choose the destination folder.")); | |
1038 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); | |
1039 pref_spacer(GENERIC_DIALOG(fdlg)->vbox, 0); | |
1040 | |
1041 file_dialog_add_button(fdlg, stock_id, ud->messages.title, file_util_fdlg_ok_cb, TRUE); | |
1042 | |
1043 file_dialog_add_path_widgets(fdlg, NULL, ud->dest_path, "move_copy", NULL, NULL); | |
1044 | |
1045 g_signal_connect(G_OBJECT(fdlg->entry), "changed", | |
1046 G_CALLBACK(file_util_dest_folder_entry_cb), ud); | |
1047 | |
1048 gtk_widget_show(GENERIC_DIALOG(fdlg)->dialog); | |
1049 } | |
1050 | |
2363 | 1051 |
2364 static GtkWidget *furm_simple_vlabel(GtkWidget *box, const gchar *text, gint expand) | 1052 static GtkWidget *furm_simple_vlabel(GtkWidget *box, const gchar *text, gint expand) |
2365 { | 1053 { |
2366 GtkWidget *vbox; | 1054 GtkWidget *vbox; |
2367 GtkWidget *label; | 1055 GtkWidget *label; |
2375 gtk_widget_show(label); | 1063 gtk_widget_show(label); |
2376 | 1064 |
2377 return vbox; | 1065 return vbox; |
2378 } | 1066 } |
2379 | 1067 |
2380 static GtkTreeViewColumn *file_util_rename_multiple_add_column(RenameDataMult *rd, const gchar *text, gint n) | 1068 |
2381 { | 1069 static void file_util_dialog_init_source_dest(UtilityData *ud) |
2382 GtkTreeViewColumn *column; | 1070 { |
2383 GtkCellRenderer *renderer; | 1071 GtkTreeModel *store; |
2384 | |
2385 column = gtk_tree_view_column_new(); | |
2386 gtk_tree_view_column_set_title(column, text); | |
2387 gtk_tree_view_column_set_min_width(column, 4); | |
2388 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_GROW_ONLY); | |
2389 renderer = gtk_cell_renderer_text_new(); | |
2390 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
2391 gtk_tree_view_column_add_attribute(column, renderer, "text", n); | |
2392 gtk_tree_view_append_column(GTK_TREE_VIEW(rd->listview), column); | |
2393 | |
2394 return column; | |
2395 } | |
2396 | |
2397 static void file_util_rename_multiple_destroy_cb(GtkWidget *widget, gpointer data) | |
2398 { | |
2399 RenameDataMult *rd = data; | |
2400 | |
2401 if (rd->update_idle_id != -1) g_source_remove(rd->update_idle_id); | |
2402 | |
2403 g_free(rd); | |
2404 } | |
2405 | |
2406 static void file_util_rename_multiple_do(GList *source_list, GtkWidget *parent) | |
2407 { | |
2408 RenameDataMult *rd; | |
2409 GtkWidget *pane; | |
2410 GtkWidget *scrolled; | |
2411 GtkListStore *store; | |
2412 GtkTreeSelection *selection; | 1072 GtkTreeSelection *selection; |
2413 GtkTreeViewColumn *column; | 1073 GtkWidget *box; |
2414 GtkWidget *hbox; | 1074 GtkWidget *hbox; |
2415 GtkWidget *vbox; | |
2416 GtkWidget *box2; | 1075 GtkWidget *box2; |
2417 GtkWidget *table; | 1076 GtkWidget *table; |
2418 GtkWidget *combo; | 1077 GtkWidget *combo; |
2419 GList *work; | 1078 GtkWidget *page; |
2420 const gchar *name; | 1079 |
2421 | 1080 ud->gd = file_util_gen_dlg(ud->messages.title, GQ_WMCLASS, "dlg_confirm", |
2422 rd = g_new0(RenameDataMult, 1); | 1081 ud->parent, FALSE, file_util_cancel_cb, ud); |
2423 | 1082 |
2424 rd->fdlg = file_util_file_dlg( _("Rename"), GQ_WMCLASS, "dlg_rename", parent, | 1083 |
2425 file_util_rename_multiple_close_cb, rd); | 1084 box = generic_dialog_add_message(ud->gd, NULL, ud->messages.question, NULL); |
2426 generic_dialog_add_message(GENERIC_DIALOG(rd->fdlg), NULL, _("Rename multiple files"), NULL); | 1085 generic_dialog_add_button(ud->gd, GTK_STOCK_OK, ud->messages.title, file_util_ok_cb, TRUE); |
2427 file_dialog_add_button(rd->fdlg, GTK_STOCK_OK, _("_Rename"), file_util_rename_multiple_cb, TRUE); | 1086 |
2428 | 1087 box = pref_group_new(box, TRUE, ud->messages.desc_flist, GTK_ORIENTATION_HORIZONTAL); |
2429 rd->fdlg->source_fd = file_data_ref(source_list->data); | 1088 |
2430 rd->fdlg->dest_path = NULL; | 1089 ud->listview = file_util_dialog_add_list(box, ud->flist, FALSE); |
2431 | 1090 file_util_dialog_add_list_column(ud->listview, _("Sidecars"), UTILITY_COLUMN_SIDECARS); |
2432 rd->rename_type = RENAME_TYPE_MANUAL; | 1091 |
2433 | 1092 file_util_dialog_add_list_column(ud->listview, _("New name"), UTILITY_COLUMN_DEST_NAME); |
2434 rd->update_idle_id = -1; | 1093 |
2435 | 1094 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ud->listview)); |
2436 vbox = GENERIC_DIALOG(rd->fdlg)->vbox; | |
2437 | |
2438 pane = gtk_hpaned_new(); | |
2439 gtk_box_pack_start(GTK_BOX(vbox), pane, TRUE, TRUE, 0); | |
2440 gtk_widget_show(pane); | |
2441 | |
2442 scrolled = gtk_scrolled_window_new(NULL, NULL); | |
2443 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); | |
2444 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), | |
2445 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); | |
2446 gtk_paned_pack1(GTK_PANED(pane), scrolled, TRUE, TRUE); | |
2447 gtk_widget_show(scrolled); | |
2448 | |
2449 store = gtk_list_store_new(4, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); | |
2450 rd->listview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); | |
2451 g_object_unref(store); | |
2452 | |
2453 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(rd->listview), TRUE); | |
2454 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(rd->listview), FALSE); | |
2455 | |
2456 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(rd->listview)); | |
2457 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE); | 1095 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE); |
2458 gtk_tree_selection_set_select_function(selection, file_util_rename_multiple_select_cb, rd, NULL); | 1096 gtk_tree_selection_set_select_function(selection, file_util_preview_cb, ud, NULL); |
2459 | 1097 |
2460 file_util_rename_multiple_add_column(rd, _("Original Name"), RENAME_COLUMN_NAME); | 1098 |
2461 column = file_util_rename_multiple_add_column(rd, _("Preview"), RENAME_COLUMN_PREVIEW); | 1099 // column = file_util_rename_multiple_add_column(rd, _("Preview"), RENAME_COLUMN_PREVIEW); |
2462 gtk_tree_view_column_set_visible(column, FALSE); | 1100 // gtk_tree_view_column_set_visible(column, FALSE); |
2463 | 1101 |
2464 gtk_tree_view_set_reorderable(GTK_TREE_VIEW(rd->listview), TRUE); | 1102 gtk_tree_view_set_reorderable(GTK_TREE_VIEW(ud->listview), TRUE); |
1103 | |
1104 store = gtk_tree_view_get_model(GTK_TREE_VIEW(ud->listview)); | |
2465 g_signal_connect(G_OBJECT(store), "row_changed", | 1105 g_signal_connect(G_OBJECT(store), "row_changed", |
2466 G_CALLBACK(file_util_rename_multiple_preview_order_cb), rd); | 1106 G_CALLBACK(file_util_rename_preview_order_cb), ud); |
2467 gtk_widget_set_size_request(rd->listview, 250, 150); | 1107 gtk_widget_set_size_request(ud->listview, 300, 150); |
2468 | 1108 |
2469 gtk_container_add(GTK_CONTAINER(scrolled), rd->listview); | 1109 generic_dialog_add_image(ud->gd, box, NULL, NULL, NULL, NULL, FALSE); |
2470 gtk_widget_show(rd->listview); | 1110 |
2471 | 1111 // gtk_container_add(GTK_CONTAINER(scrolled), view); |
2472 work = source_list; | 1112 gtk_widget_show(ud->gd->dialog); |
2473 while (work) | 1113 |
2474 { | 1114 |
2475 FileData *fd = work->data; | 1115 ud->notebook = gtk_notebook_new(); |
2476 GtkTreeIter iter; | 1116 |
2477 | 1117 gtk_box_pack_start(GTK_BOX(ud->gd->vbox), ud->notebook, FALSE, FALSE, 0); |
2478 gtk_list_store_append(store, &iter); | 1118 gtk_widget_show(ud->notebook); |
2479 gtk_list_store_set(store, &iter, RENAME_COLUMN_FD, fd, RENAME_COLUMN_PATH, fd->path, RENAME_COLUMN_NAME, fd->name, -1); | 1119 |
2480 | 1120 |
2481 work = work->next; | 1121 page = gtk_vbox_new(FALSE, PREF_PAD_GAP); |
2482 } | 1122 gtk_notebook_append_page(GTK_NOTEBOOK(ud->notebook), page, gtk_label_new(_("Manual rename"))); |
2483 | 1123 gtk_widget_show(page); |
2484 filelist_free(source_list); | 1124 |
2485 | 1125 table = pref_table_new(page, 2, 2, FALSE, FALSE); |
2486 rd->imd = image_new(TRUE); | |
2487 g_object_set(G_OBJECT(rd->imd->pr), "zoom_expand", FALSE, NULL); | |
2488 gtk_widget_set_size_request(rd->imd->widget, DIALOG_DEF_IMAGE_DIM_X, DIALOG_DEF_IMAGE_DIM_Y); | |
2489 gtk_paned_pack2(GTK_PANED(pane), rd->imd->widget, FALSE, TRUE); | |
2490 gtk_widget_show(rd->imd->widget); | |
2491 | |
2492 hbox = gtk_hbox_new(FALSE, 0); | |
2493 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); | |
2494 gtk_widget_show(hbox); | |
2495 | |
2496 rd->combo_type = gtk_combo_box_new_text(); | |
2497 | |
2498 gtk_combo_box_append_text(GTK_COMBO_BOX(rd->combo_type), _("Manual rename")); | |
2499 gtk_combo_box_append_text(GTK_COMBO_BOX(rd->combo_type), _("Formatted rename")); | |
2500 gtk_combo_box_append_text(GTK_COMBO_BOX(rd->combo_type), _("Auto rename")); | |
2501 | |
2502 gtk_combo_box_set_active(GTK_COMBO_BOX(rd->combo_type), rd->rename_type); | |
2503 | |
2504 g_signal_connect(G_OBJECT(rd->combo_type), "changed", | |
2505 G_CALLBACK(file_util_rename_multiple_auto_change), rd); | |
2506 gtk_box_pack_end(GTK_BOX(hbox), rd->combo_type, FALSE, FALSE, 0); | |
2507 gtk_widget_show(rd->combo_type); | |
2508 | |
2509 rd->rename_box = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, 0); | |
2510 table = pref_table_new(rd->rename_box, 2, 2, FALSE, FALSE); | |
2511 | 1126 |
2512 pref_table_label(table, 0, 0, _("Original name:"), 1.0); | 1127 pref_table_label(table, 0, 0, _("Original name:"), 1.0); |
2513 rd->rename_label = pref_table_label(table, 1, 0, rd->fdlg->source_fd->name, 0.0); | 1128 ud->rename_label = pref_table_label(table, 1, 0, "", 0.0); |
2514 | 1129 |
2515 pref_table_label(table, 0, 1, _("New name:"), 1.0); | 1130 pref_table_label(table, 0, 1, _("New name:"), 1.0); |
2516 | 1131 |
2517 rd->rename_entry = gtk_entry_new(); | 1132 ud->rename_entry = gtk_entry_new(); |
2518 gtk_table_attach(GTK_TABLE(table), rd->rename_entry, 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 0, 0); | 1133 gtk_table_attach(GTK_TABLE(table), ud->rename_entry, 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 0, 0); |
2519 generic_dialog_attach_default(GENERIC_DIALOG(rd->fdlg), rd->rename_entry); | 1134 generic_dialog_attach_default(GENERIC_DIALOG(ud->gd), ud->rename_entry); |
2520 gtk_widget_grab_focus(rd->rename_entry); | 1135 gtk_widget_grab_focus(ud->rename_entry); |
2521 | 1136 |
2522 name = rd->fdlg->source_fd->name; | 1137 g_signal_connect(G_OBJECT(ud->rename_entry), "changed", |
2523 gtk_entry_set_text(GTK_ENTRY(rd->rename_entry), name); | 1138 G_CALLBACK(file_util_rename_preview_entry_cb), ud); |
2524 gtk_editable_select_region(GTK_EDITABLE(rd->rename_entry), 0, filename_base_length(name)); | 1139 |
2525 gtk_widget_show(rd->rename_entry); | 1140 gtk_widget_show(ud->rename_entry); |
2526 | 1141 |
2527 rd->auto_box = gtk_vbox_new(FALSE, PREF_PAD_GAP); | 1142 page = gtk_vbox_new(FALSE, PREF_PAD_GAP); |
2528 gtk_box_pack_start(GTK_BOX(vbox), rd->auto_box, FALSE, FALSE, 0); | 1143 gtk_notebook_append_page(GTK_NOTEBOOK(ud->notebook), page, gtk_label_new(_("Auto rename"))); |
2529 /* do not show it here */ | 1144 gtk_widget_show(page); |
2530 | 1145 |
2531 hbox = pref_box_new(rd->auto_box, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_GAP); | 1146 |
1147 hbox = pref_box_new(page, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_GAP); | |
2532 | 1148 |
2533 box2 = furm_simple_vlabel(hbox, _("Begin text"), TRUE); | 1149 box2 = furm_simple_vlabel(hbox, _("Begin text"), TRUE); |
2534 | 1150 |
2535 combo = history_combo_new(&rd->auto_entry_front, "", "numerical_rename_prefix", -1); | 1151 combo = history_combo_new(&ud->auto_entry_front, "", "numerical_rename_prefix", -1); |
2536 g_signal_connect(G_OBJECT(rd->auto_entry_front), "changed", | 1152 g_signal_connect(G_OBJECT(ud->auto_entry_front), "changed", |
2537 G_CALLBACK(file_util_rename_multiple_preview_entry_cb), rd); | 1153 G_CALLBACK(file_util_rename_preview_entry_cb), ud); |
2538 gtk_box_pack_start(GTK_BOX(box2), combo, TRUE, TRUE, 0); | 1154 gtk_box_pack_start(GTK_BOX(box2), combo, TRUE, TRUE, 0); |
2539 gtk_widget_show(combo); | 1155 gtk_widget_show(combo); |
2540 | 1156 |
2541 box2 = furm_simple_vlabel(hbox, _("Start #"), FALSE); | 1157 box2 = furm_simple_vlabel(hbox, _("Start #"), FALSE); |
2542 | 1158 |
2543 rd->auto_spin_start = pref_spin_new(box2, NULL, NULL, | 1159 ud->auto_spin_start = pref_spin_new(box2, NULL, NULL, |
2544 0.0, 1000000.0, 1.0, 0, 1.0, | 1160 0.0, 1000000.0, 1.0, 0, 1.0, |
2545 G_CALLBACK(file_util_rename_multiple_preview_adj_cb), rd); | 1161 G_CALLBACK(file_util_rename_preview_adj_cb), ud); |
2546 | 1162 |
2547 box2 = furm_simple_vlabel(hbox, _("End text"), TRUE); | 1163 box2 = furm_simple_vlabel(hbox, _("End text"), TRUE); |
2548 | 1164 |
2549 combo = history_combo_new(&rd->auto_entry_end, "", "numerical_rename_suffix", -1); | 1165 combo = history_combo_new(&ud->auto_entry_end, "", "numerical_rename_suffix", -1); |
2550 g_signal_connect(G_OBJECT(rd->auto_entry_end), "changed", | 1166 g_signal_connect(G_OBJECT(ud->auto_entry_end), "changed", |
2551 G_CALLBACK(file_util_rename_multiple_preview_entry_cb), rd); | 1167 G_CALLBACK(file_util_rename_preview_entry_cb), ud); |
2552 gtk_box_pack_start(GTK_BOX(box2), combo, TRUE, TRUE, 0); | 1168 gtk_box_pack_start(GTK_BOX(box2), combo, TRUE, TRUE, 0); |
2553 gtk_widget_show(combo); | 1169 gtk_widget_show(combo); |
2554 | 1170 |
2555 rd->auto_spin_pad = pref_spin_new(rd->auto_box, _("Padding:"), NULL, | 1171 ud->auto_spin_pad = pref_spin_new(page, _("Padding:"), NULL, |
2556 1.0, 8.0, 1.0, 0, 1.0, | 1172 1.0, 8.0, 1.0, 0, 1.0, |
2557 G_CALLBACK(file_util_rename_multiple_preview_adj_cb), rd); | 1173 G_CALLBACK(file_util_rename_preview_adj_cb), ud); |
2558 | 1174 |
2559 rd->format_box = gtk_vbox_new(FALSE, PREF_PAD_GAP); | 1175 page = gtk_vbox_new(FALSE, PREF_PAD_GAP); |
2560 gtk_box_pack_start(GTK_BOX(vbox), rd->format_box, FALSE, FALSE, 0); | 1176 gtk_notebook_append_page(GTK_NOTEBOOK(ud->notebook), page, gtk_label_new(_("Formatted rename"))); |
2561 /* do not show it here */ | 1177 gtk_widget_show(page); |
2562 | 1178 |
2563 hbox = pref_box_new(rd->format_box, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_GAP); | 1179 hbox = pref_box_new(page, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_GAP); |
2564 | 1180 |
2565 box2 = furm_simple_vlabel(hbox, _("Format (* = original name, ## = numbers)"), TRUE); | 1181 box2 = furm_simple_vlabel(hbox, _("Format (* = original name, ## = numbers)"), TRUE); |
2566 | 1182 |
2567 combo = history_combo_new(&rd->format_entry, "", "auto_rename_format", -1); | 1183 combo = history_combo_new(&ud->format_entry, "", "auto_rename_format", -1); |
2568 g_signal_connect(G_OBJECT(rd->format_entry), "changed", | 1184 g_signal_connect(G_OBJECT(ud->format_entry), "changed", |
2569 G_CALLBACK(file_util_rename_multiple_preview_entry_cb), rd); | 1185 G_CALLBACK(file_util_rename_preview_entry_cb), ud); |
2570 gtk_box_pack_start(GTK_BOX(box2), combo, TRUE, TRUE, 0); | 1186 gtk_box_pack_start(GTK_BOX(box2), combo, TRUE, TRUE, 0); |
2571 gtk_widget_show(combo); | 1187 gtk_widget_show(combo); |
2572 | 1188 |
2573 box2 = furm_simple_vlabel(hbox, _("Start #"), FALSE); | 1189 box2 = furm_simple_vlabel(hbox, _("Start #"), FALSE); |
2574 | 1190 |
2575 rd->format_spin = pref_spin_new(box2, NULL, NULL, | 1191 ud->format_spin = pref_spin_new(box2, NULL, NULL, |
2576 0.0, 1000000.0, 1.0, 0, 1.0, | 1192 0.0, 1000000.0, 1.0, 0, 1.0, |
2577 G_CALLBACK(file_util_rename_multiple_preview_adj_cb), rd); | 1193 G_CALLBACK(file_util_rename_preview_adj_cb), ud); |
2578 | 1194 |
2579 image_change_fd(rd->imd, rd->fdlg->source_fd, 0.0); | 1195 // gtk_combo_box_set_active(GTK_COMBO_BOX(ud->combo_type), 0); /* callback will take care of the rest */ |
2580 | 1196 |
2581 g_signal_connect(G_OBJECT(GENERIC_DIALOG(rd->fdlg)->dialog), "destroy", | 1197 file_util_dialog_list_select(ud->listview, 0); |
2582 G_CALLBACK(file_util_rename_multiple_destroy_cb), rd); | 1198 } |
2583 | 1199 |
2584 gtk_widget_show(GENERIC_DIALOG(rd->fdlg)->dialog); | 1200 |
2585 } | 1201 void file_util_dialog_run(UtilityData *ud) |
2586 | 1202 { |
2587 /* | 1203 switch (ud->phase) |
2588 * rename single file | 1204 { |
2589 */ | 1205 case UTILITY_PHASE_START: |
2590 | 1206 /* create the dialogs */ |
2591 static void file_util_rename_single(FileDataSingle *fds); | 1207 switch (ud->type) |
2592 | 1208 { |
2593 static void file_util_rename_single_ok_cb(GenericDialog *gd, gpointer data) | 1209 case UTILITY_TYPE_DELETE: |
2594 { | 1210 case UTILITY_TYPE_DELETE_LINK: |
2595 FileDataSingle *fds = data; | 1211 case UTILITY_TYPE_DELETE_FOLDER: |
2596 fds->confirmed = TRUE; | 1212 case UTILITY_TYPE_EDITOR: |
2597 file_util_rename_single(fds); | 1213 file_util_dialog_init_simple_list(ud); |
2598 } | 1214 break; |
2599 | 1215 case UTILITY_TYPE_RENAME: |
2600 static void file_util_rename_single_cancel_cb(GenericDialog *gd, gpointer data) | 1216 file_util_dialog_init_source_dest(ud); |
2601 { | 1217 break; |
2602 FileDataSingle *fds = data; | 1218 case UTILITY_TYPE_COPY: |
2603 file_data_single_free(fds); | 1219 case UTILITY_TYPE_MOVE: |
2604 } | 1220 case UTILITY_TYPE_FILTER: |
2605 | 1221 file_util_dialog_init_dest_folder(ud); |
2606 static void file_util_rename_single(FileDataSingle *fds) | 1222 break; |
2607 { | 1223 } |
2608 if (isfile(fds->dest) && !fds->confirmed) | 1224 ud->phase = UTILITY_PHASE_ENTERING; |
2609 { | 1225 break; |
2610 GenericDialog *gd; | 1226 case UTILITY_PHASE_ENTERING: |
2611 | 1227 /* FIXME use file_data_sc_check_ci_dest to detect problems and eventually go back to PHASE_START |
2612 gd = file_util_gen_dlg(_("Overwrite file"), GQ_WMCLASS, "dlg_confirm", | 1228 or to PHASE_CANCEL */ |
2613 NULL, TRUE, | 1229 |
2614 file_util_rename_single_cancel_cb, fds); | 1230 |
2615 | 1231 ud->phase = UTILITY_PHASE_CHECKED; |
2616 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, | 1232 case UTILITY_PHASE_CHECKED: |
2617 _("Overwrite file?"), | 1233 file_util_perform_ci(ud); |
2618 _("Replace existing file by renaming new file.")); | 1234 break; |
2619 pref_spacer(gd->vbox, 0); | 1235 |
2620 | 1236 case UTILITY_PHASE_CANCEL: |
2621 generic_dialog_add_button(gd, GTK_STOCK_OK, _("_Overwrite"), file_util_rename_single_ok_cb, TRUE); | 1237 case UTILITY_PHASE_DONE: |
2622 generic_dialog_add_image(gd, NULL, | 1238 file_data_sc_free_ci_list(ud->flist); |
2623 file_data_new_simple(fds->dest), _("Existing file"), | 1239 file_data_sc_free_ci_list(ud->dlist); |
2624 fds->source_fd, _("New file"), TRUE); | 1240 if (ud->source_fd) file_data_sc_free_ci(ud->source_fd); |
2625 | 1241 file_util_data_free(ud); |
2626 gtk_widget_show(gd->dialog); | 1242 break; |
2627 | 1243 } |
1244 } | |
1245 | |
1246 | |
1247 | |
1248 | |
1249 static gint file_util_unlink(FileData *fd) | |
1250 { | |
1251 } | |
1252 | |
1253 | |
1254 static void file_util_delete_full(FileData *source_fd, GList *source_list, GtkWidget *parent, UtilityPhase phase) | |
1255 { | |
1256 UtilityData *ud; | |
1257 GList *flist = filelist_copy(source_list); | |
1258 | |
1259 if (source_fd) | |
1260 flist = g_list_append(flist, file_data_ref(source_fd)); | |
1261 | |
1262 if (!file_data_sc_add_ci_delete_list(flist)) | |
1263 { | |
1264 file_util_warning_dialog(_("File deletion failed"), _("Another operation in progress.\n"), GTK_STOCK_DIALOG_ERROR, NULL); | |
1265 filelist_free(flist); | |
2628 return; | 1266 return; |
2629 } | 1267 } |
1268 | |
1269 ud = file_util_data_new(UTILITY_TYPE_DELETE); | |
1270 | |
1271 ud->phase = phase; | |
1272 | |
1273 ud->source_fd = NULL; | |
1274 ud->flist = flist; | |
1275 ud->dlist = NULL; | |
1276 ud->parent = parent; | |
1277 | |
1278 ud->messages.title = _("Delete"); | |
1279 ud->messages.question = _("Delete files?"); | |
1280 ud->messages.desc_flist = _("This will delete the following files"); | |
1281 ud->messages.desc_dlist = ""; | |
1282 ud->messages.desc_source_fd = ""; | |
1283 ud->messages.fail = _("File deletion failed"); | |
1284 | |
1285 file_util_dialog_run(ud); | |
1286 } | |
1287 | |
1288 static void file_util_move_full(FileData *source_fd, GList *source_list, const gchar *dest_path, GtkWidget *parent, UtilityPhase phase) | |
1289 { | |
1290 UtilityData *ud; | |
1291 GList *flist = filelist_copy(source_list); | |
1292 | |
1293 if (source_fd) | |
1294 flist = g_list_append(flist, file_data_ref(source_fd)); | |
1295 | |
1296 if (!file_data_sc_add_ci_move_list(flist, dest_path)) | |
1297 { | |
1298 file_util_warning_dialog(_("Move failed"), _("Another operation in progress.\n"), GTK_STOCK_DIALOG_ERROR, NULL); | |
1299 filelist_free(flist); | |
1300 return; | |
1301 } | |
1302 | |
1303 ud = file_util_data_new(UTILITY_TYPE_MOVE); | |
1304 | |
1305 ud->phase = phase; | |
1306 | |
1307 ud->source_fd = NULL; | |
1308 ud->flist = flist; | |
1309 ud->dlist = NULL; | |
1310 ud->parent = parent; | |
1311 | |
1312 ud->dest_path = g_strdup(dest_path ? dest_path : ""); | |
1313 | |
1314 ud->messages.title = _("Move"); | |
1315 ud->messages.question = _("Move files?"); | |
1316 ud->messages.desc_flist = _("This will move the following files"); | |
1317 ud->messages.desc_dlist = ""; | |
1318 ud->messages.desc_source_fd = ""; | |
1319 ud->messages.fail = _("Move failed"); | |
1320 | |
1321 file_util_dialog_run(ud); | |
1322 } | |
1323 static void file_util_copy_full(FileData *source_fd, GList *source_list, const gchar *dest_path, GtkWidget *parent, UtilityPhase phase) | |
1324 { | |
1325 UtilityData *ud; | |
1326 GList *flist = filelist_copy(source_list); | |
1327 | |
1328 if (source_fd) | |
1329 flist = g_list_append(flist, file_data_ref(source_fd)); | |
1330 | |
1331 if (!file_data_sc_add_ci_copy_list(flist, dest_path)) | |
1332 { | |
1333 file_util_warning_dialog(_("Copy failed"), _("Another operation in progress.\n"), GTK_STOCK_DIALOG_ERROR, NULL); | |
1334 filelist_free(flist); | |
1335 return; | |
1336 } | |
1337 | |
1338 ud = file_util_data_new(UTILITY_TYPE_COPY); | |
1339 | |
1340 ud->phase = phase; | |
1341 | |
1342 ud->source_fd = NULL; | |
1343 ud->flist = flist; | |
1344 ud->dlist = NULL; | |
1345 ud->parent = parent; | |
1346 | |
1347 ud->dest_path = g_strdup(dest_path ? dest_path : ""); | |
1348 | |
1349 ud->messages.title = _("Copy"); | |
1350 ud->messages.question = _("Copy files?"); | |
1351 ud->messages.desc_flist = _("This will copy the following files"); | |
1352 ud->messages.desc_dlist = ""; | |
1353 ud->messages.desc_source_fd = ""; | |
1354 ud->messages.fail = _("Copy failed"); | |
1355 | |
1356 file_util_dialog_run(ud); | |
1357 } | |
1358 | |
1359 static void file_util_rename_full(FileData *source_fd, GList *source_list, const gchar *dest_path, GtkWidget *parent, UtilityPhase phase) | |
1360 { | |
1361 UtilityData *ud; | |
1362 GList *flist = filelist_copy(source_list); | |
1363 | |
1364 if (source_fd) | |
1365 flist = g_list_append(flist, file_data_ref(source_fd)); | |
1366 | |
1367 if (!file_data_sc_add_ci_rename_list(flist, dest_path)) | |
1368 { | |
1369 file_util_warning_dialog(_("Rename failed"), _("Another operation in progress.\n"), GTK_STOCK_DIALOG_ERROR, NULL); | |
1370 filelist_free(flist); | |
1371 return; | |
1372 } | |
1373 | |
1374 ud = file_util_data_new(UTILITY_TYPE_RENAME); | |
1375 | |
1376 ud->phase = phase; | |
1377 | |
1378 ud->source_fd = NULL; | |
1379 ud->flist = flist; | |
1380 ud->dlist = NULL; | |
1381 ud->parent = parent; | |
1382 | |
1383 ud->messages.title = _("Rename"); | |
1384 ud->messages.question = _("Rename files?"); | |
1385 ud->messages.desc_flist = _("This will rename the following files"); | |
1386 ud->messages.desc_dlist = ""; | |
1387 ud->messages.desc_source_fd = ""; | |
1388 ud->messages.fail = _("Rename failed"); | |
1389 | |
1390 file_util_dialog_run(ud); | |
1391 } | |
1392 | |
1393 static void file_util_start_editor_full(gint n, FileData *source_fd, GList *source_list, const gchar *dest_path, GtkWidget *parent, UtilityPhase phase) | |
1394 { | |
1395 UtilityData *ud; | |
1396 GList *flist = filelist_copy(source_list); | |
1397 | |
1398 if (source_fd) | |
1399 flist = g_list_append(flist, file_data_ref(source_fd)); | |
1400 | |
1401 if (!file_data_sc_add_ci_unspecified_list(flist, dest_path)) | |
1402 { | |
1403 file_util_warning_dialog(_("Can't run external editor"), _("Another operation in progress.\n"), GTK_STOCK_DIALOG_ERROR, NULL); | |
1404 filelist_free(flist); | |
1405 return; | |
1406 } | |
1407 | |
1408 if (editor_is_filter(n)) | |
1409 ud = file_util_data_new(UTILITY_TYPE_FILTER); | |
2630 else | 1410 else |
2631 { | 1411 ud = file_util_data_new(UTILITY_TYPE_EDITOR); |
2632 /* | 1412 |
2633 GList *list = g_list_append(NULL, file_data_ref(fds->source_fd)); | 1413 |
2634 file_util_do_move_list(list, FALSE, TRUE); | 1414 /* ask for destination if we don't have it */ |
2635 filelist_free(list); | 1415 if (ud->type == UTILITY_TYPE_FILTER && dest_path == NULL) phase = UTILITY_PHASE_START; |
1416 | |
1417 ud->phase = phase; | |
1418 | |
1419 ud->external_command = n; | |
1420 | |
1421 ud->source_fd = NULL; | |
1422 ud->flist = flist; | |
1423 ud->dlist = NULL; | |
1424 ud->parent = parent; | |
1425 | |
1426 ud->dest_path = g_strdup(dest_path ? dest_path : ""); | |
1427 | |
1428 ud->messages.title = _("Editor"); | |
1429 ud->messages.question = _("Run editor?"); | |
1430 ud->messages.desc_flist = _("This will copy the following files"); | |
1431 ud->messages.desc_dlist = ""; | |
1432 ud->messages.desc_source_fd = ""; | |
1433 ud->messages.fail = _("External command failed"); | |
1434 | |
1435 file_util_dialog_run(ud); | |
1436 } | |
1437 | |
1438 | |
1439 /* FIXME: */ | |
1440 void file_util_create_dir(const gchar *path, GtkWidget *parent) | |
1441 { | |
1442 } | |
1443 gint file_util_rename_dir(FileData *source_fd, const gchar *new_path, GtkWidget *parent) | |
1444 { | |
1445 } | |
1446 | |
1447 /* full-featured entru points | |
2636 */ | 1448 */ |
2637 if (!file_data_add_change_info(fds->source_fd, FILEDATA_CHANGE_RENAME, fds->source_fd->path, fds->dest) || | 1449 |
2638 !rename_file_ext(fds->source_fd)) | 1450 void file_util_delete(FileData *source_fd, GList *source_list, GtkWidget *parent) |
2639 { | 1451 { |
2640 gchar *text = g_strdup_printf(_("Unable to rename file:\n%s\nto:\n%s"), fds->source_fd->name, filename_from_path(fds->dest)); | 1452 file_util_delete_full(source_fd, source_list, parent, UTILITY_PHASE_START); |
2641 file_util_warning_dialog(_("Error renaming file"), text, GTK_STOCK_DIALOG_ERROR, NULL); | 1453 } |
2642 g_free(text); | 1454 |
2643 } | 1455 void file_util_copy(FileData *source_fd, GList *source_list, const gchar *dest_path, GtkWidget *parent) |
2644 | 1456 { |
2645 } | 1457 file_util_copy_full(source_fd, source_list, dest_path, parent, UTILITY_PHASE_START); |
2646 file_data_single_free(fds); | 1458 } |
2647 } | 1459 void file_util_move(FileData *source_fd, GList *source_list, const gchar *dest_path, GtkWidget *parent) |
2648 | 1460 { |
2649 static void file_util_rename_single_cb(FileDialog *fdlg, gpointer data) | 1461 file_util_move_full(source_fd, source_list, dest_path, parent, UTILITY_PHASE_START); |
2650 { | 1462 } |
2651 const gchar *name; | |
2652 gchar *path; | |
2653 | |
2654 name = gtk_entry_get_text(GTK_ENTRY(fdlg->entry)); | |
2655 path = g_build_filename(fdlg->dest_path, name, NULL); | |
2656 | |
2657 if (strlen(name) == 0 || strcmp(fdlg->source_fd->path, path) == 0) | |
2658 { | |
2659 g_free(path); | |
2660 return; | |
2661 } | |
2662 | |
2663 file_util_rename_single(file_data_single_new(fdlg->source_fd, path, fdlg->type)); | |
2664 | |
2665 g_free(path); | |
2666 file_dialog_close(fdlg); | |
2667 } | |
2668 | |
2669 static void file_util_rename_single_close_cb(FileDialog *fdlg, gpointer data) | |
2670 { | |
2671 file_dialog_close(fdlg); | |
2672 } | |
2673 | |
2674 static void file_util_rename_single_do(FileData *source_fd, GtkWidget *parent) | |
2675 { | |
2676 FileDialog *fdlg; | |
2677 GtkWidget *table; | |
2678 const gchar *name; | |
2679 | |
2680 fdlg = file_util_file_dlg(_("Rename"), GQ_WMCLASS, "dlg_rename", parent, | |
2681 file_util_rename_single_close_cb, NULL); | |
2682 | |
2683 generic_dialog_add_message(GENERIC_DIALOG(fdlg), NULL, _("Rename file"), NULL); | |
2684 generic_dialog_add_image(GENERIC_DIALOG(fdlg), NULL, source_fd, NULL, NULL, NULL, FALSE); | |
2685 | |
2686 file_dialog_add_button(fdlg, GTK_STOCK_OK, _("_Rename"), file_util_rename_single_cb, TRUE); | |
2687 | |
2688 fdlg->source_fd = file_data_ref(source_fd); | |
2689 fdlg->dest_path = remove_level_from_path(source_fd->path); | |
2690 | |
2691 table = pref_table_new(GENERIC_DIALOG(fdlg)->vbox, 2, 2, FALSE, FALSE); | |
2692 | |
2693 pref_table_label(table, 0, 0, _("Original name:"), 1.0); | |
2694 pref_table_label(table, 1, 0, fdlg->source_fd->name, 0.0); | |
2695 | |
2696 pref_table_label(table, 0, 1, _("New name:"), 1.0); | |
2697 | |
2698 fdlg->entry = gtk_entry_new(); | |
2699 gtk_table_attach(GTK_TABLE(table), fdlg->entry, 1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 0, 0); | |
2700 generic_dialog_attach_default(GENERIC_DIALOG(fdlg), fdlg->entry); | |
2701 gtk_widget_grab_focus(fdlg->entry); | |
2702 | |
2703 name = fdlg->source_fd->name; | |
2704 gtk_entry_set_text(GTK_ENTRY(fdlg->entry), name); | |
2705 gtk_editable_select_region(GTK_EDITABLE(fdlg->entry), 0, filename_base_length(name)); | |
2706 gtk_widget_show(fdlg->entry); | |
2707 | |
2708 gtk_widget_show(GENERIC_DIALOG(fdlg)->dialog); | |
2709 } | |
2710 | |
2711 void file_util_rename(FileData *source_fd, GList *source_list, GtkWidget *parent) | 1463 void file_util_rename(FileData *source_fd, GList *source_list, GtkWidget *parent) |
2712 { | 1464 { |
2713 if (!source_fd && !source_list) return; | 1465 file_util_rename_full(source_fd, source_list, NULL, parent, UTILITY_PHASE_START); |
2714 | 1466 } |
2715 if (source_fd) | 1467 |
2716 { | 1468 /* these avoid the location entry dialog unless there is an error, list must be files only and |
2717 file_util_rename_single_do(source_fd, parent); | 1469 * dest_path must be a valid directory path |
2718 } | 1470 */ |
2719 else if (!source_list->next) | 1471 void file_util_move_simple(GList *list, const gchar *dest_path, GtkWidget *parent) |
2720 { | 1472 { |
2721 file_util_rename_single_do(source_list->data, parent); | 1473 file_util_move_full(NULL, list, dest_path, parent, UTILITY_PHASE_ENTERING); |
2722 filelist_free(source_list); | 1474 } |
2723 } | 1475 void file_util_copy_simple(GList *list, const gchar *dest_path, GtkWidget *parent) |
2724 else | 1476 { |
2725 { | 1477 file_util_copy_full(NULL, list, dest_path, parent, UTILITY_PHASE_ENTERING); |
2726 file_util_rename_multiple_do(source_list, parent); | 1478 } |
2727 } | 1479 void file_util_rename_simple(FileData *fd, const gchar *dest_path, GtkWidget *parent) |
2728 } | 1480 { |
2729 | 1481 file_util_rename_full(fd, NULL, dest_path, parent, UTILITY_PHASE_ENTERING); |
2730 /* | 1482 } |
2731 *-------------------------------------------------------------------------- | 1483 |
2732 * Create directory routines | 1484 |
2733 *-------------------------------------------------------------------------- | 1485 void file_util_start_editor_from_file(gint n, FileData *fd, GtkWidget *parent) |
2734 */ | 1486 { |
2735 | 1487 file_util_start_editor_full(n, fd, NULL, NULL, parent, UTILITY_PHASE_ENTERING); |
2736 static void file_util_create_dir_do(const gchar *base, const gchar *name) | 1488 } |
2737 { | 1489 |
2738 gchar *path; | 1490 void file_util_start_editor_from_filelist(gint n, GList *list, GtkWidget *parent) |
2739 | 1491 { |
2740 path = g_build_filename(base, name, NULL); | 1492 file_util_start_editor_full(n, NULL, list, NULL, parent, UTILITY_PHASE_ENTERING); |
2741 | 1493 } |
2742 if (isdir(path)) | 1494 |
2743 { | 1495 void file_util_start_filter_from_file(gint n, FileData *fd, const gchar *dest_path, GtkWidget *parent) |
2744 gchar *text = g_strdup_printf(_("The folder:\n%s\nalready exists."), name); | 1496 { |
2745 file_util_warning_dialog(_("Folder exists"), text, GTK_STOCK_DIALOG_INFO, NULL); | 1497 file_util_start_editor_full(n, fd, NULL, dest_path, parent, UTILITY_PHASE_ENTERING); |
2746 g_free(text); | 1498 } |
2747 } | 1499 |
2748 else if (isname(path)) | 1500 void file_util_start_filter_from_filelist(gint n, GList *list, const gchar *dest_path, GtkWidget *parent) |
2749 { | 1501 { |
2750 gchar *text = g_strdup_printf(_("The path:\n%s\nalready exists as a file."), name); | 1502 file_util_start_editor_full(n, NULL, list, dest_path, parent, UTILITY_PHASE_ENTERING); |
2751 file_util_warning_dialog(_("Could not create folder"), text, GTK_STOCK_DIALOG_INFO, NULL); | 1503 } |
2752 g_free(text); | 1504 |
2753 } | |
2754 else | |
2755 { | |
2756 if (!mkdir_utf8(path, 0755)) | |
2757 { | |
2758 gchar *text = g_strdup_printf(_("Unable to create folder:\n%s"), name); | |
2759 file_util_warning_dialog(_("Error creating folder"), text, GTK_STOCK_DIALOG_ERROR, NULL); | |
2760 g_free(text); | |
2761 } | |
2762 } | |
2763 | |
2764 g_free(path); | |
2765 } | |
2766 | |
2767 static void file_util_create_dir_cb(FileDialog *fdlg, gpointer data) | |
2768 { | |
2769 const gchar *name; | |
2770 | |
2771 name = gtk_entry_get_text(GTK_ENTRY(fdlg->entry)); | |
2772 | |
2773 if (strlen(name) == 0) return; | |
2774 | |
2775 if (name[0] == G_DIR_SEPARATOR) | |
2776 { | |
2777 gchar *buf; | |
2778 buf = remove_level_from_path(name); | |
2779 file_util_create_dir_do(buf, filename_from_path(name)); | |
2780 g_free(buf); | |
2781 } | |
2782 else | |
2783 { | |
2784 file_util_create_dir_do(fdlg->dest_path, name); | |
2785 } | |
2786 | |
2787 file_dialog_close(fdlg); | |
2788 } | |
2789 | |
2790 static void file_util_create_dir_close_cb(FileDialog *fdlg, gpointer data) | |
2791 { | |
2792 file_dialog_close(fdlg); | |
2793 } | |
2794 | |
2795 void file_util_create_dir(const gchar *path, GtkWidget *parent) | |
2796 { | |
2797 FileDialog *fdlg; | |
2798 gchar *text; | |
2799 | |
2800 if (!isdir(path)) return; | |
2801 | |
2802 fdlg = file_util_file_dlg(_("New folder"), GQ_WMCLASS, "dlg_newdir", parent, | |
2803 file_util_create_dir_close_cb, NULL); | |
2804 | |
2805 text = g_strdup_printf(_("Create folder in:\n%s\nnamed:"), path); | |
2806 generic_dialog_add_message(GENERIC_DIALOG(fdlg), NULL, NULL, text); | |
2807 g_free(text); | |
2808 | |
2809 file_dialog_add_button(fdlg, GTK_STOCK_OK, NULL, file_util_create_dir_cb, TRUE); | |
2810 | |
2811 fdlg->dest_path = g_strdup(path); | |
2812 | |
2813 fdlg->entry = gtk_entry_new(); | |
2814 gtk_box_pack_start(GTK_BOX(GENERIC_DIALOG(fdlg)->vbox), fdlg->entry, FALSE, FALSE, 0); | |
2815 generic_dialog_attach_default(GENERIC_DIALOG(fdlg), fdlg->entry); | |
2816 gtk_widget_grab_focus(fdlg->entry); | |
2817 gtk_widget_show(fdlg->entry); | |
2818 | |
2819 gtk_widget_show(GENERIC_DIALOG(fdlg)->dialog); | |
2820 } | |
2821 | |
2822 gint file_util_rename_dir(FileData *old_fd, const gchar *new_path, GtkWidget *parent) | |
2823 { | |
2824 const gchar *old_name; | |
2825 const gchar *new_name; | |
2826 | |
2827 if (!old_fd || !new_path || !isdir(old_fd->path)) return FALSE; | |
2828 | |
2829 old_name = old_fd->name; | |
2830 new_name = filename_from_path(new_path); | |
2831 | |
2832 if (isdir(new_path)) | |
2833 { | |
2834 gchar *text = g_strdup_printf(_("The folder:\n%s\nalready exists."), new_name); | |
2835 file_util_warning_dialog(_("Folder exists"), text, GTK_STOCK_DIALOG_INFO, parent); | |
2836 g_free(text); | |
2837 | |
2838 return FALSE; | |
2839 } | |
2840 | |
2841 if (isname(new_path)) | |
2842 { | |
2843 gchar *text = g_strdup_printf(_("The path:\n%s\nalready exists as a file."), new_name); | |
2844 file_util_warning_dialog(_("Rename failed"), text, GTK_STOCK_DIALOG_INFO,parent); | |
2845 g_free(text); | |
2846 | |
2847 return FALSE; | |
2848 } | |
2849 if (!file_data_add_change_info(old_fd, FILEDATA_CHANGE_RENAME, old_fd->path, new_path) || | |
2850 !rename_file_ext(old_fd)) | |
2851 { | |
2852 gchar *text = g_strdup_printf(_("Failed to rename %s to %s."), old_name, new_name); | |
2853 file_util_warning_dialog(_("Rename failed"), text, GTK_STOCK_DIALOG_ERROR, parent); | |
2854 g_free(text); | |
2855 | |
2856 return FALSE; | |
2857 } | |
2858 | |
2859 return TRUE; | |
2860 } | |
2861 | 1505 |
2862 /* | 1506 /* |
2863 *-------------------------------------------------------------------------- | 1507 *-------------------------------------------------------------------------- |
2864 * Delete directory routines | 1508 * Delete directory routines |
2865 *-------------------------------------------------------------------------- | 1509 *-------------------------------------------------------------------------- |
2866 */ | 1510 */ |
2867 | 1511 |
2868 /* The plan is to eventually make all of utilops.c | 1512 // FIXME |
2869 * use UtilityData and UtilityType. | 1513 |
2870 * And clean up the above mess someday. | 1514 |
2871 */ | |
2872 | |
2873 typedef enum { | |
2874 UTILITY_TYPE_NONE = 0, | |
2875 UTILITY_TYPE_COPY, | |
2876 UTILITY_TYPE_MOVE, | |
2877 UTILITY_TYPE_RENAME, | |
2878 UTILITY_TYPE_DELETE, | |
2879 UTILITY_TYPE_DELETE_LINK, | |
2880 UTILITY_TYPE_DELETE_FOLDER | |
2881 } UtilityType; | |
2882 | |
2883 typedef struct _UtilityData UtilityData; | |
2884 struct _UtilityData { | |
2885 UtilityType type; | |
2886 FileData *source_fd; | |
2887 GList *dlist; | |
2888 GList *flist; | |
2889 | |
2890 GenericDialog *gd; | |
2891 }; | |
2892 | |
2893 enum { | |
2894 UTILITY_COLUMN_FD = 0, | |
2895 UTILITY_COLUMN_PATH, | |
2896 UTILITY_COLUMN_NAME, | |
2897 UTILITY_COLUMN_COUNT | |
2898 }; | |
2899 | |
2900 | |
2901 #define UTILITY_LIST_MIN_WIDTH 250 | |
2902 #define UTILITY_LIST_MIN_HEIGHT 150 | |
2903 | |
2904 /* thumbnail spec has a max depth of 4 (.thumb??/fail/appname/??.png) */ | |
2905 #define UTILITY_DELETE_MAX_DEPTH 5 | |
2906 | |
2907 | |
2908 static void file_util_data_free(UtilityData *ud) | |
2909 { | |
2910 if (!ud) return; | |
2911 | |
2912 file_data_unref(ud->source_fd); | |
2913 filelist_free(ud->dlist); | |
2914 filelist_free(ud->flist); | |
2915 | |
2916 if (ud->gd) generic_dialog_close(ud->gd); | |
2917 | |
2918 g_free(ud); | |
2919 } | |
2920 | |
2921 static GtkTreeViewColumn *file_util_dialog_add_list_column(GtkWidget *view, const gchar *text, gint n) | |
2922 { | |
2923 GtkTreeViewColumn *column; | |
2924 GtkCellRenderer *renderer; | |
2925 | |
2926 column = gtk_tree_view_column_new(); | |
2927 gtk_tree_view_column_set_title(column, text); | |
2928 gtk_tree_view_column_set_min_width(column, 4); | |
2929 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_GROW_ONLY); | |
2930 renderer = gtk_cell_renderer_text_new(); | |
2931 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
2932 gtk_tree_view_column_add_attribute(column, renderer, "text", n); | |
2933 gtk_tree_view_append_column(GTK_TREE_VIEW(view), column); | |
2934 | |
2935 return column; | |
2936 } | |
2937 | |
2938 static GtkWidget *file_util_dialog_add_list(GtkWidget *box, GList *list, gint full_paths) | |
2939 { | |
2940 GtkWidget *scrolled; | |
2941 GtkWidget *view; | |
2942 GtkListStore *store; | |
2943 | |
2944 scrolled = gtk_scrolled_window_new(NULL, NULL); | |
2945 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); | |
2946 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), | |
2947 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); | |
2948 gtk_box_pack_start(GTK_BOX(box), scrolled, TRUE, TRUE, 0); | |
2949 gtk_widget_show(scrolled); | |
2950 | |
2951 store = gtk_list_store_new(UTILITY_COLUMN_COUNT, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING); | |
2952 view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); | |
2953 g_object_unref(store); | |
2954 | |
2955 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), TRUE); | |
2956 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(view), FALSE); | |
2957 | |
2958 if (full_paths) | |
2959 { | |
2960 file_util_dialog_add_list_column(view, _("Location"), UTILITY_COLUMN_PATH); | |
2961 } | |
2962 else | |
2963 { | |
2964 file_util_dialog_add_list_column(view, _("Name"), UTILITY_COLUMN_NAME); | |
2965 } | |
2966 | |
2967 gtk_widget_set_size_request(view, UTILITY_LIST_MIN_WIDTH, UTILITY_LIST_MIN_HEIGHT); | |
2968 gtk_container_add(GTK_CONTAINER(scrolled), view); | |
2969 gtk_widget_show(view); | |
2970 | |
2971 while (list) | |
2972 { | |
2973 FileData *fd = list->data; | |
2974 GtkTreeIter iter; | |
2975 | |
2976 gtk_list_store_append(store, &iter); | |
2977 gtk_list_store_set(store, &iter, UTILITY_COLUMN_FD, fd, | |
2978 UTILITY_COLUMN_PATH, fd->path, | |
2979 UTILITY_COLUMN_NAME, fd->name, -1); | |
2980 | |
2981 list = list->next; | |
2982 } | |
2983 | |
2984 return view; | |
2985 } | |
2986 | |
2987 static gboolean file_util_delete_dir_preview_cb(GtkTreeSelection *selection, GtkTreeModel *store, | |
2988 GtkTreePath *tpath, gboolean path_currently_selected, | |
2989 gpointer data) | |
2990 { | |
2991 UtilityData *ud = data; | |
2992 GtkTreeIter iter; | |
2993 FileData *fd = NULL; | |
2994 | |
2995 if (path_currently_selected || | |
2996 !gtk_tree_model_get_iter(store, &iter, tpath)) return TRUE; | |
2997 | |
2998 gtk_tree_model_get(store, &iter, UTILITY_COLUMN_FD, &fd, -1); | |
2999 generic_dialog_image_set(ud->gd, fd); | |
3000 // file_data_unref(fd); | |
3001 | |
3002 return TRUE; | |
3003 } | |
3004 | |
3005 static void file_util_delete_dir_cancel_cb(GenericDialog *gd, gpointer data) | |
3006 { | |
3007 UtilityData *ud = data; | |
3008 | |
3009 ud->gd = NULL; | |
3010 file_util_data_free(ud); | |
3011 } | |
3012 | 1515 |
3013 FileData *file_util_delete_dir_empty_path(FileData *fd, gint real_content, gint level) | 1516 FileData *file_util_delete_dir_empty_path(FileData *fd, gint real_content, gint level) |
3014 { | 1517 { |
3015 GList *dlist = NULL; | 1518 GList *dlist = NULL; |
3016 GList *flist = NULL; | 1519 GList *flist = NULL; |
3197 ud->dlist = NULL; | 1700 ud->dlist = NULL; |
3198 ud->flist = NULL; | 1701 ud->flist = NULL; |
3199 | 1702 |
3200 ud->gd = file_util_gen_dlg(_("Delete folder"), GQ_WMCLASS, "dlg_confirm", | 1703 ud->gd = file_util_gen_dlg(_("Delete folder"), GQ_WMCLASS, "dlg_confirm", |
3201 parent, TRUE, | 1704 parent, TRUE, |
3202 file_util_delete_dir_cancel_cb, ud); | 1705 file_util_cancel_cb, ud); |
3203 | 1706 |
3204 text = g_strdup_printf(_("This will delete the symbolic link:\n\n%s\n\n" | 1707 text = g_strdup_printf(_("This will delete the symbolic link:\n\n%s\n\n" |
3205 "The folder this link points to will not be deleted."), | 1708 "The folder this link points to will not be deleted."), |
3206 fd->path); | 1709 fd->path); |
3207 generic_dialog_add_message(ud->gd, GTK_STOCK_DIALOG_QUESTION, | 1710 generic_dialog_add_message(ud->gd, GTK_STOCK_DIALOG_QUESTION, |
3280 dlist = NULL; | 1783 dlist = NULL; |
3281 ud->flist = filelist_sort_path(flist); | 1784 ud->flist = filelist_sort_path(flist); |
3282 flist = NULL; | 1785 flist = NULL; |
3283 | 1786 |
3284 ud->gd = file_util_gen_dlg(_("Delete folder"), GQ_WMCLASS, "dlg_confirm", | 1787 ud->gd = file_util_gen_dlg(_("Delete folder"), GQ_WMCLASS, "dlg_confirm", |
3285 parent, TRUE, file_util_delete_dir_cancel_cb, ud); | 1788 parent, TRUE, file_util_cancel_cb, ud); |
3286 generic_dialog_add_button(ud->gd, GTK_STOCK_DELETE, NULL, file_util_delete_dir_ok_cb, TRUE); | 1789 generic_dialog_add_button(ud->gd, GTK_STOCK_DELETE, NULL, file_util_delete_dir_ok_cb, TRUE); |
3287 | 1790 |
3288 text = g_strdup_printf(_("This will delete the folder:\n\n%s\n\n" | 1791 text = g_strdup_printf(_("This will delete the folder:\n\n%s\n\n" |
3289 "The contents of this folder will also be deleted."), | 1792 "The contents of this folder will also be deleted."), |
3290 fd->path); | 1793 fd->path); |
3296 box = pref_group_new(box, TRUE, _("Contents:"), GTK_ORIENTATION_HORIZONTAL); | 1799 box = pref_group_new(box, TRUE, _("Contents:"), GTK_ORIENTATION_HORIZONTAL); |
3297 | 1800 |
3298 view = file_util_dialog_add_list(box, ud->flist, FALSE); | 1801 view = file_util_dialog_add_list(box, ud->flist, FALSE); |
3299 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); | 1802 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); |
3300 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); | 1803 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); |
3301 gtk_tree_selection_set_select_function(selection, file_util_delete_dir_preview_cb, ud, NULL); | 1804 gtk_tree_selection_set_select_function(selection, file_util_preview_cb, ud, NULL); |
3302 | 1805 |
3303 generic_dialog_add_image(ud->gd, box, NULL, NULL, NULL, NULL, FALSE); | 1806 generic_dialog_add_image(ud->gd, box, NULL, NULL, NULL, NULL, FALSE); |
3304 | 1807 |
3305 box_append_safe_delete_status(ud->gd); | 1808 box_append_safe_delete_status(ud->gd); |
3306 | 1809 |
3309 | 1812 |
3310 g_list_free(rlist); | 1813 g_list_free(rlist); |
3311 filelist_free(dlist); | 1814 filelist_free(dlist); |
3312 filelist_free(flist); | 1815 filelist_free(flist); |
3313 } | 1816 } |
1817 | |
1818 | |
1819 void file_util_copy_path_to_clipboard(FileData *fd) | |
1820 { | |
1821 GtkClipboard *clipboard; | |
1822 | |
1823 if (!fd || !*fd->path) return; | |
1824 | |
1825 clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY); | |
1826 gtk_clipboard_set_text(clipboard, g_shell_quote(fd->path), -1); | |
1827 } | |
1828 | |
1829 void file_util_copy_path_list_to_clipboard(GList *list) | |
1830 { | |
1831 GtkClipboard *clipboard; | |
1832 GList *work; | |
1833 GString *new; | |
1834 | |
1835 clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY); | |
1836 | |
1837 new = g_string_new(""); | |
1838 work = list; | |
1839 while (work) { | |
1840 FileData *fd = work->data; | |
1841 work = work->next; | |
1842 | |
1843 if (!fd || !*fd->path) continue; | |
1844 | |
1845 g_string_append(new, g_shell_quote(fd->path)); | |
1846 if (work) g_string_append_c(new, ' '); | |
1847 } | |
1848 | |
1849 gtk_clipboard_set_text(clipboard, new->str, new->len); | |
1850 g_string_free(new, TRUE); | |
1851 } |