Mercurial > geeqie.yaz
comparison src/utilops.c @ 112:b15d4c18168f
Fri Nov 17 19:06:19 2006 John Ellis <johne@verizon.net>
* ui_fileops.[ch]: Add path_list_lstat() to obtain a path listing that
does not follow symbolic links.
* utilops.[ch]: Add file_util_delete_dir(), and support functions.
* view_dir_list.c: Add delete to folder popup menu.
* view_dir_tree.c: Add delete to folder popup menu, and set rename and
delete sensitive only when parent folder is writable.
author | gqview |
---|---|
date | Sat, 18 Nov 2006 00:12:22 +0000 |
parents | a10fc0308c12 |
children | 53b2bfdcff69 |
comparison
equal
deleted
inserted
replaced
111:3a69a7a3f461 | 112:b15d4c18168f |
---|---|
12 | 12 |
13 #include "gqview.h" | 13 #include "gqview.h" |
14 #include "utilops.h" | 14 #include "utilops.h" |
15 | 15 |
16 | 16 |
17 #include "cache.h" | |
17 #include "cache_maint.h" | 18 #include "cache_maint.h" |
18 #include "collect.h" | 19 #include "collect.h" |
19 #include "dupe.h" | 20 #include "dupe.h" |
20 #include "filelist.h" | 21 #include "filelist.h" |
21 #include "image.h" | 22 #include "image.h" |
22 #include "img-view.h" | 23 #include "img-view.h" |
23 #include "layout.h" | 24 #include "layout.h" |
24 #include "search.h" | 25 #include "search.h" |
26 #include "thumb_standard.h" | |
25 #include "ui_bookmark.h" | 27 #include "ui_bookmark.h" |
26 #include "ui_fileops.h" | 28 #include "ui_fileops.h" |
27 #include "ui_misc.h" | 29 #include "ui_misc.h" |
28 #include "ui_tabcomp.h" | 30 #include "ui_tabcomp.h" |
29 | 31 |
137 */ | 139 */ |
138 | 140 |
139 #define DIALOG_DEF_IMAGE_DIM_X 200 | 141 #define DIALOG_DEF_IMAGE_DIM_X 200 |
140 #define DIALOG_DEF_IMAGE_DIM_Y 150 | 142 #define DIALOG_DEF_IMAGE_DIM_Y 150 |
141 | 143 |
142 static void generic_dialog_add_image(GenericDialog *gd, const gchar *path1, const gchar *header1, | 144 static void generic_dialog_add_image(GenericDialog *gd, GtkWidget *box, |
145 const gchar *path1, const gchar *header1, | |
143 const gchar *path2, const gchar *header2, | 146 const gchar *path2, const gchar *header2, |
144 gint show_filename) | 147 gint show_filename) |
145 { | 148 { |
146 ImageWindow *imd; | 149 ImageWindow *imd; |
147 GtkWidget *hbox = NULL; | 150 GtkWidget *hbox = NULL; |
148 GtkWidget *vbox; | 151 GtkWidget *vbox; |
149 GtkWidget *label = NULL; | 152 GtkWidget *label = NULL; |
150 | 153 |
154 if (!box) box = gd->vbox; | |
155 | |
151 if (path2) | 156 if (path2) |
152 { | 157 { |
153 hbox = pref_box_new(gd->vbox, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE); | 158 hbox = pref_box_new(box, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE); |
154 } | 159 } |
155 | 160 |
156 /* image 1 */ | 161 /* image 1 */ |
157 | 162 |
158 vbox = gtk_vbox_new(FALSE, PREF_PAD_GAP); | 163 vbox = gtk_vbox_new(FALSE, PREF_PAD_GAP); |
166 gtk_box_pack_start(GTK_BOX(hbox), sep, FALSE, FALSE, 0); | 171 gtk_box_pack_start(GTK_BOX(hbox), sep, FALSE, FALSE, 0); |
167 gtk_widget_show(sep); | 172 gtk_widget_show(sep); |
168 } | 173 } |
169 else | 174 else |
170 { | 175 { |
171 gtk_box_pack_start(GTK_BOX(gd->vbox), vbox, TRUE, TRUE, PREF_PAD_GAP); | 176 gtk_box_pack_start(GTK_BOX(box), vbox, TRUE, TRUE, PREF_PAD_GAP); |
172 } | 177 } |
173 gtk_widget_show(vbox); | 178 gtk_widget_show(vbox); |
174 | 179 |
175 if (header1) | 180 if (header1) |
176 { | 181 { |
180 pref_label_bold(head, TRUE, FALSE); | 185 pref_label_bold(head, TRUE, FALSE); |
181 gtk_misc_set_alignment(GTK_MISC(head), 0.0, 0.5); | 186 gtk_misc_set_alignment(GTK_MISC(head), 0.0, 0.5); |
182 } | 187 } |
183 | 188 |
184 imd = image_new(FALSE); | 189 imd = image_new(FALSE); |
190 g_object_set(G_OBJECT(imd->pr), "zoom_expand", FALSE, NULL); | |
185 gtk_widget_set_size_request(imd->widget, DIALOG_DEF_IMAGE_DIM_X, DIALOG_DEF_IMAGE_DIM_Y); | 191 gtk_widget_set_size_request(imd->widget, DIALOG_DEF_IMAGE_DIM_X, DIALOG_DEF_IMAGE_DIM_Y); |
186 gtk_box_pack_start(GTK_BOX(vbox), imd->widget, TRUE, TRUE, 0); | 192 gtk_box_pack_start(GTK_BOX(vbox), imd->widget, TRUE, TRUE, 0); |
187 image_change_path(imd, path1, 0.0); | 193 image_change_path(imd, path1, 0.0); |
188 gtk_widget_show(imd->widget); | 194 gtk_widget_show(imd->widget); |
189 | 195 |
211 pref_label_bold(head, TRUE, FALSE); | 217 pref_label_bold(head, TRUE, FALSE); |
212 gtk_misc_set_alignment(GTK_MISC(head), 0.0, 0.5); | 218 gtk_misc_set_alignment(GTK_MISC(head), 0.0, 0.5); |
213 } | 219 } |
214 | 220 |
215 imd = image_new(FALSE); | 221 imd = image_new(FALSE); |
222 g_object_set(G_OBJECT(imd->pr), "zoom_expand", FALSE, NULL); | |
216 gtk_widget_set_size_request(imd->widget, DIALOG_DEF_IMAGE_DIM_X, DIALOG_DEF_IMAGE_DIM_Y); | 223 gtk_widget_set_size_request(imd->widget, DIALOG_DEF_IMAGE_DIM_X, DIALOG_DEF_IMAGE_DIM_Y); |
217 gtk_box_pack_start(GTK_BOX(vbox), imd->widget, TRUE, TRUE, 0); | 224 gtk_box_pack_start(GTK_BOX(vbox), imd->widget, TRUE, TRUE, 0); |
218 image_change_path(imd, path2, 0.0); | 225 image_change_path(imd, path2, 0.0); |
219 gtk_widget_show(imd->widget); | 226 gtk_widget_show(imd->widget); |
220 | 227 |
507 generic_dialog_add_button(gd, GTK_STOCK_YES, _("_Overwrite"), file_util_move_multiple_ok_cb, TRUE); | 514 generic_dialog_add_button(gd, GTK_STOCK_YES, _("_Overwrite"), file_util_move_multiple_ok_cb, TRUE); |
508 fdm->yes_all_button = generic_dialog_add_button(gd, NULL, _("Overwrite _all"), | 515 fdm->yes_all_button = generic_dialog_add_button(gd, NULL, _("Overwrite _all"), |
509 file_util_move_multiple_all_cb, FALSE); | 516 file_util_move_multiple_all_cb, FALSE); |
510 generic_dialog_add_button(gd, GTK_STOCK_GOTO_LAST, _("S_kip all"), file_util_move_multiple_skip_all_cb, FALSE); | 517 generic_dialog_add_button(gd, GTK_STOCK_GOTO_LAST, _("S_kip all"), file_util_move_multiple_skip_all_cb, FALSE); |
511 generic_dialog_add_button(gd, GTK_STOCK_GO_FORWARD, _("_Skip"), file_util_move_multiple_skip_cb, FALSE); | 518 generic_dialog_add_button(gd, GTK_STOCK_GO_FORWARD, _("_Skip"), file_util_move_multiple_skip_cb, FALSE); |
512 generic_dialog_add_image(gd, fdm->dest, _("Existing file"), fdm->source, _("New file"), TRUE); | 519 generic_dialog_add_image(gd, NULL, fdm->dest, _("Existing file"), fdm->source, _("New file"), TRUE); |
513 | 520 |
514 /* rename option */ | 521 /* rename option */ |
515 | 522 |
516 fdm->rename = FALSE; | 523 fdm->rename = FALSE; |
517 fdm->rename_all = FALSE; | 524 fdm->rename_all = FALSE; |
824 _("Overwrite file?"), | 831 _("Overwrite file?"), |
825 _("Replace existing file with new file.")); | 832 _("Replace existing file with new file.")); |
826 pref_spacer(gd->vbox, 0); | 833 pref_spacer(gd->vbox, 0); |
827 | 834 |
828 generic_dialog_add_button(gd, GTK_STOCK_OK, _("_Overwrite"), file_util_move_single_ok_cb, TRUE); | 835 generic_dialog_add_button(gd, GTK_STOCK_OK, _("_Overwrite"), file_util_move_single_ok_cb, TRUE); |
829 generic_dialog_add_image(gd, fds->dest, _("Existing file"), fds->source, _("New file"), TRUE); | 836 generic_dialog_add_image(gd, NULL, fds->dest, _("Existing file"), fds->source, _("New file"), TRUE); |
830 | 837 |
831 /* rename option */ | 838 /* rename option */ |
832 | 839 |
833 fds->rename = FALSE; | 840 fds->rename = FALSE; |
834 fds->rename_auto = FALSE; | 841 fds->rename_auto = FALSE; |
1476 "GQview", "dlg_confirm", parent, TRUE, | 1483 "GQview", "dlg_confirm", parent, TRUE, |
1477 file_util_delete_multiple_cancel_cb, source_list); | 1484 file_util_delete_multiple_cancel_cb, source_list); |
1478 | 1485 |
1479 generic_dialog_add_message(gd, NULL, _("Delete multiple files"), NULL); | 1486 generic_dialog_add_message(gd, NULL, _("Delete multiple files"), NULL); |
1480 | 1487 |
1481 generic_dialog_add_image(gd, NULL, NULL, NULL, NULL, TRUE); | 1488 generic_dialog_add_image(gd, NULL, NULL, NULL, NULL, NULL, TRUE); |
1482 imd = g_object_get_data(G_OBJECT(gd->dialog), "img_image"); | 1489 imd = g_object_get_data(G_OBJECT(gd->dialog), "img_image"); |
1483 image_set_button_func(imd, file_util_delete_multiple_review_button_cb, gd); | 1490 image_set_button_func(imd, file_util_delete_multiple_review_button_cb, gd); |
1484 image_set_scroll_func(imd, file_util_delete_multiple_review_scroll_cb, gd); | 1491 image_set_scroll_func(imd, file_util_delete_multiple_review_scroll_cb, gd); |
1485 | 1492 |
1486 hbox = pref_box_new(gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP); | 1493 hbox = pref_box_new(gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP); |
1565 | 1572 |
1566 base = remove_level_from_path(path); | 1573 base = remove_level_from_path(path); |
1567 pref_table_label(table, 1, 1, base, 0.0); | 1574 pref_table_label(table, 1, 1, base, 0.0); |
1568 g_free(base); | 1575 g_free(base); |
1569 | 1576 |
1570 generic_dialog_add_image(gd, path, NULL, NULL, NULL, FALSE); | 1577 generic_dialog_add_image(gd, NULL, path, NULL, NULL, NULL, FALSE); |
1571 | 1578 |
1572 box_append_safe_delete_status(gd); | 1579 box_append_safe_delete_status(gd); |
1573 | 1580 |
1574 generic_dialog_add_button(gd, GTK_STOCK_DELETE, NULL, file_util_delete_ok_cb, TRUE); | 1581 generic_dialog_add_button(gd, GTK_STOCK_DELETE, NULL, file_util_delete_ok_cb, TRUE); |
1575 | 1582 |
1714 _("Overwrite file?"), | 1721 _("Overwrite file?"), |
1715 _("Replace existing file by renaming new file.")); | 1722 _("Replace existing file by renaming new file.")); |
1716 pref_spacer(gd->vbox, 0); | 1723 pref_spacer(gd->vbox, 0); |
1717 | 1724 |
1718 generic_dialog_add_button(gd, GTK_STOCK_OK, _("_Overwrite"), file_util_rename_multiple_ok_cb, TRUE); | 1725 generic_dialog_add_button(gd, GTK_STOCK_OK, _("_Overwrite"), file_util_rename_multiple_ok_cb, TRUE); |
1719 generic_dialog_add_image(gd, fd->dest_path, _("Existing file"), fd->source_path, _("New file"), TRUE); | 1726 generic_dialog_add_image(gd, NULL, |
1727 fd->dest_path, _("Existing file"), | |
1728 fd->source_path, _("New file"), TRUE); | |
1720 | 1729 |
1721 gtk_widget_hide(GENERIC_DIALOG(fd)->dialog); | 1730 gtk_widget_hide(GENERIC_DIALOG(fd)->dialog); |
1722 | 1731 |
1723 gtk_widget_show(gd->dialog); | 1732 gtk_widget_show(gd->dialog); |
1724 return; | 1733 return; |
2299 } | 2308 } |
2300 | 2309 |
2301 path_list_free(source_list); | 2310 path_list_free(source_list); |
2302 | 2311 |
2303 rd->imd = image_new(TRUE); | 2312 rd->imd = image_new(TRUE); |
2313 g_object_set(G_OBJECT(rd->imd->pr), "zoom_expand", FALSE, NULL); | |
2304 gtk_widget_set_size_request(rd->imd->widget, DIALOG_DEF_IMAGE_DIM_X, DIALOG_DEF_IMAGE_DIM_Y); | 2314 gtk_widget_set_size_request(rd->imd->widget, DIALOG_DEF_IMAGE_DIM_X, DIALOG_DEF_IMAGE_DIM_Y); |
2305 gtk_paned_pack2(GTK_PANED(pane), rd->imd->widget, FALSE, TRUE); | 2315 gtk_paned_pack2(GTK_PANED(pane), rd->imd->widget, FALSE, TRUE); |
2306 gtk_widget_show(rd->imd->widget); | 2316 gtk_widget_show(rd->imd->widget); |
2307 | 2317 |
2308 hbox = gtk_hbox_new(FALSE, 0); | 2318 hbox = gtk_hbox_new(FALSE, 0); |
2433 _("Overwrite file?"), | 2443 _("Overwrite file?"), |
2434 _("Replace existing file by renaming new file.")); | 2444 _("Replace existing file by renaming new file.")); |
2435 pref_spacer(gd->vbox, 0); | 2445 pref_spacer(gd->vbox, 0); |
2436 | 2446 |
2437 generic_dialog_add_button(gd, GTK_STOCK_OK, _("_Overwrite"), file_util_rename_single_ok_cb, TRUE); | 2447 generic_dialog_add_button(gd, GTK_STOCK_OK, _("_Overwrite"), file_util_rename_single_ok_cb, TRUE); |
2438 generic_dialog_add_image(gd, fds->dest, _("Existing file"), fds->source, _("New file"), TRUE); | 2448 generic_dialog_add_image(gd, NULL, |
2449 fds->dest, _("Existing file"), | |
2450 fds->source, _("New file"), TRUE); | |
2439 | 2451 |
2440 gtk_widget_show(gd->dialog); | 2452 gtk_widget_show(gd->dialog); |
2441 | 2453 |
2442 return; | 2454 return; |
2443 } | 2455 } |
2490 | 2502 |
2491 fd = file_util_file_dlg(_("Rename - GQview"), "GQview", "dlg_rename", parent, | 2503 fd = file_util_file_dlg(_("Rename - GQview"), "GQview", "dlg_rename", parent, |
2492 file_util_rename_single_close_cb, NULL); | 2504 file_util_rename_single_close_cb, NULL); |
2493 | 2505 |
2494 generic_dialog_add_message(GENERIC_DIALOG(fd), NULL, _("Rename file"), NULL); | 2506 generic_dialog_add_message(GENERIC_DIALOG(fd), NULL, _("Rename file"), NULL); |
2495 generic_dialog_add_image(GENERIC_DIALOG(fd), source_path, NULL, NULL, NULL, FALSE); | 2507 generic_dialog_add_image(GENERIC_DIALOG(fd), NULL, source_path, NULL, NULL, NULL, FALSE); |
2496 | 2508 |
2497 file_dialog_add_button(fd, GTK_STOCK_OK, _("_Rename"), file_util_rename_single_cb, TRUE); | 2509 file_dialog_add_button(fd, GTK_STOCK_OK, _("_Rename"), file_util_rename_single_cb, TRUE); |
2498 | 2510 |
2499 fd->source_path = g_strdup(source_path); | 2511 fd->source_path = g_strdup(source_path); |
2500 fd->dest_path = remove_level_from_path(source_path); | 2512 fd->dest_path = remove_level_from_path(source_path); |
2668 } | 2680 } |
2669 | 2681 |
2670 return TRUE; | 2682 return TRUE; |
2671 } | 2683 } |
2672 | 2684 |
2685 /* | |
2686 *-------------------------------------------------------------------------- | |
2687 * Delete directory routines | |
2688 *-------------------------------------------------------------------------- | |
2689 */ | |
2690 | |
2691 /* The plan is to eventually make all of utilops.c | |
2692 * use UtilityData and UtilityType. | |
2693 * And clean up the above mess someday. | |
2694 */ | |
2695 | |
2696 typedef enum { | |
2697 UTILITY_TYPE_NONE = 0, | |
2698 UTILITY_TYPE_COPY, | |
2699 UTILITY_TYPE_MOVE, | |
2700 UTILITY_TYPE_RENAME, | |
2701 UTILITY_TYPE_DELETE, | |
2702 UTILITY_TYPE_DELETE_LINK, | |
2703 UTILITY_TYPE_DELETE_FOLDER | |
2704 } UtilityType; | |
2705 | |
2706 typedef struct _UtilityData UtilityData; | |
2707 struct _UtilityData { | |
2708 UtilityType type; | |
2709 gchar *source_path; | |
2710 GList *dlist; | |
2711 GList *flist; | |
2712 | |
2713 GenericDialog *gd; | |
2714 }; | |
2715 | |
2716 #define UTILITY_LIST_MIN_WIDTH 250 | |
2717 #define UTILITY_LIST_MIN_HEIGHT 150 | |
2718 | |
2719 /* thumbnail spec has a max depth of 4 (.thumb??/fail/appname/??.png) */ | |
2720 #define UTILITY_DELETE_MAX_DEPTH 5 | |
2721 | |
2722 | |
2723 static void file_util_data_free(UtilityData *ud) | |
2724 { | |
2725 if (!ud) return; | |
2726 | |
2727 g_free(ud->source_path); | |
2728 path_list_free(ud->dlist); | |
2729 path_list_free(ud->flist); | |
2730 | |
2731 if (ud->gd) generic_dialog_close(ud->gd); | |
2732 | |
2733 g_free(ud); | |
2734 } | |
2735 | |
2736 static GtkTreeViewColumn *file_util_dialog_add_list_column(GtkWidget *view, const gchar *text, gint n) | |
2737 { | |
2738 GtkTreeViewColumn *column; | |
2739 GtkCellRenderer *renderer; | |
2740 | |
2741 column = gtk_tree_view_column_new(); | |
2742 gtk_tree_view_column_set_title(column, text); | |
2743 gtk_tree_view_column_set_min_width(column, 4); | |
2744 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_GROW_ONLY); | |
2745 renderer = gtk_cell_renderer_text_new(); | |
2746 gtk_tree_view_column_pack_start(column, renderer, TRUE); | |
2747 gtk_tree_view_column_add_attribute(column, renderer, "text", n); | |
2748 gtk_tree_view_append_column(GTK_TREE_VIEW(view), column); | |
2749 | |
2750 return column; | |
2751 } | |
2752 | |
2753 static GtkWidget *file_util_dialog_add_list(GtkWidget *box, GList *list, gint full_paths) | |
2754 { | |
2755 GtkWidget *scrolled; | |
2756 GtkWidget *view; | |
2757 GtkListStore *store; | |
2758 | |
2759 scrolled = gtk_scrolled_window_new(NULL, NULL); | |
2760 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); | |
2761 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scrolled), | |
2762 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); | |
2763 gtk_box_pack_start(GTK_BOX(box), scrolled, TRUE, TRUE, 0); | |
2764 gtk_widget_show(scrolled); | |
2765 | |
2766 store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); | |
2767 view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); | |
2768 g_object_unref(store); | |
2769 | |
2770 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), TRUE); | |
2771 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(view), FALSE); | |
2772 | |
2773 if (full_paths) | |
2774 { | |
2775 file_util_dialog_add_list_column(view, _("Location"), 0); | |
2776 } | |
2777 else | |
2778 { | |
2779 file_util_dialog_add_list_column(view, _("Name"), 1); | |
2780 } | |
2781 | |
2782 gtk_widget_set_size_request(view, UTILITY_LIST_MIN_WIDTH, UTILITY_LIST_MIN_HEIGHT); | |
2783 gtk_container_add(GTK_CONTAINER(scrolled), view); | |
2784 gtk_widget_show(view); | |
2785 | |
2786 while (list) | |
2787 { | |
2788 gchar *path = list->data; | |
2789 GtkTreeIter iter; | |
2790 | |
2791 gtk_list_store_append(store, &iter); | |
2792 gtk_list_store_set(store, &iter, 0, path, | |
2793 1, filename_from_path(path), -1); | |
2794 | |
2795 list = list->next; | |
2796 } | |
2797 | |
2798 return view; | |
2799 } | |
2800 | |
2801 static gboolean file_util_delete_dir_preview_cb(GtkTreeSelection *selection, GtkTreeModel *store, | |
2802 GtkTreePath *tpath, gboolean path_currently_selected, | |
2803 gpointer data) | |
2804 { | |
2805 UtilityData *ud = data; | |
2806 GtkTreeIter iter; | |
2807 gchar *path = NULL; | |
2808 | |
2809 if (path_currently_selected || | |
2810 !gtk_tree_model_get_iter(store, &iter, tpath)) return TRUE; | |
2811 | |
2812 gtk_tree_model_get(store, &iter, 0, &path, -1); | |
2813 generic_dialog_image_set(ud->gd, path); | |
2814 g_free(path); | |
2815 | |
2816 return TRUE; | |
2817 } | |
2818 | |
2819 static void file_util_delete_dir_cancel_cb(GenericDialog *gd, gpointer data) | |
2820 { | |
2821 UtilityData *ud = data; | |
2822 | |
2823 ud->gd = NULL; | |
2824 file_util_data_free(ud); | |
2825 } | |
2826 | |
2827 static gchar *file_util_delete_dir_empty_path(const gchar *path, gint real_content, gint level) | |
2828 { | |
2829 GList *dlist = NULL; | |
2830 GList *flist = NULL; | |
2831 GList *work; | |
2832 gchar *fail = NULL; | |
2833 | |
2834 if (debug) printf("deltree into: %s\n", path); | |
2835 | |
2836 level++; | |
2837 if (level > UTILITY_DELETE_MAX_DEPTH) | |
2838 { | |
2839 printf("folder recursion depth past %d, giving up\n", UTILITY_DELETE_MAX_DEPTH); | |
2840 return g_strdup(path); | |
2841 } | |
2842 | |
2843 if (!path_list_lstat(path, &flist, &dlist)) return g_strdup(path); | |
2844 | |
2845 work = dlist; | |
2846 while (work && !fail) | |
2847 { | |
2848 gchar *name; | |
2849 | |
2850 name = work->data; | |
2851 work = work->next; | |
2852 | |
2853 fail = file_util_delete_dir_empty_path(name, real_content, level); | |
2854 } | |
2855 | |
2856 work = flist; | |
2857 while (work && !fail) | |
2858 { | |
2859 gchar *name; | |
2860 | |
2861 name = work->data; | |
2862 work = work->next; | |
2863 | |
2864 if (debug) printf("deltree child: %s\n", name); | |
2865 | |
2866 if (real_content && !islink(name)) | |
2867 { | |
2868 if (!file_util_unlink(name)) fail = g_strdup(name); | |
2869 } | |
2870 else | |
2871 { | |
2872 if (!unlink_file(name)) fail = g_strdup(name); | |
2873 } | |
2874 } | |
2875 | |
2876 path_list_free(dlist); | |
2877 path_list_free(flist); | |
2878 | |
2879 if (!fail && !rmdir_utf8(path)) | |
2880 { | |
2881 fail = g_strdup(path); | |
2882 } | |
2883 | |
2884 if (debug) printf("deltree done: %s\n", path); | |
2885 | |
2886 return fail; | |
2887 } | |
2888 | |
2889 static void file_util_delete_dir_ok_cb(GenericDialog *gd, gpointer data) | |
2890 { | |
2891 UtilityData *ud = data; | |
2892 | |
2893 ud->gd = NULL; | |
2894 | |
2895 if (ud->type == UTILITY_TYPE_DELETE_LINK) | |
2896 { | |
2897 if (!unlink_file(ud->source_path)) | |
2898 { | |
2899 gchar *text; | |
2900 | |
2901 text = g_strdup_printf("Unable to remove symbolic link:\n %s", ud->source_path); | |
2902 file_util_warning_dialog(_("Delete failed"), text, | |
2903 GTK_STOCK_DIALOG_ERROR, NULL); | |
2904 g_free(text); | |
2905 } | |
2906 } | |
2907 else | |
2908 { | |
2909 gchar *fail = NULL; | |
2910 GList *work; | |
2911 | |
2912 work = ud->dlist; | |
2913 while (work && !fail) | |
2914 { | |
2915 gchar *path; | |
2916 | |
2917 path = work->data; | |
2918 work = work->next; | |
2919 | |
2920 fail = file_util_delete_dir_empty_path(path, FALSE, 0); | |
2921 } | |
2922 | |
2923 work = ud->flist; | |
2924 while (work && !fail) | |
2925 { | |
2926 gchar *path; | |
2927 | |
2928 path = work->data; | |
2929 work = work->next; | |
2930 | |
2931 if (debug) printf("deltree unlink: %s\n", path); | |
2932 | |
2933 if (islink(path)) | |
2934 { | |
2935 if (!unlink_file(path)) fail = g_strdup(path); | |
2936 } | |
2937 else | |
2938 { | |
2939 if (!file_util_unlink(path)) fail = g_strdup(path); | |
2940 } | |
2941 } | |
2942 | |
2943 if (!fail) | |
2944 { | |
2945 if (!rmdir_utf8(ud->source_path)) fail = g_strdup(ud->source_path); | |
2946 } | |
2947 | |
2948 if (fail) | |
2949 { | |
2950 gchar *text; | |
2951 | |
2952 text = g_strdup_printf(_("Unable to delete folder:\n\n%s"), ud->source_path); | |
2953 gd = file_util_warning_dialog(_("Delete failed"), text, GTK_STOCK_DIALOG_ERROR, NULL); | |
2954 g_free(text); | |
2955 | |
2956 if (strcmp(fail, ud->source_path) != 0) | |
2957 { | |
2958 pref_spacer(gd->vbox, PREF_PAD_GROUP); | |
2959 text = g_strdup_printf(_("Removal of folder contents failed at this file:\n\n%s"), | |
2960 fail); | |
2961 pref_label_new(gd->vbox, text); | |
2962 g_free(text); | |
2963 } | |
2964 | |
2965 g_free(fail); | |
2966 } | |
2967 } | |
2968 | |
2969 file_util_data_free(ud); | |
2970 } | |
2971 | |
2972 static GList *file_util_delete_dir_remaining_folders(GList *dlist) | |
2973 { | |
2974 GList *rlist = NULL; | |
2975 | |
2976 while (dlist) | |
2977 { | |
2978 gchar *path; | |
2979 const gchar *name; | |
2980 | |
2981 path = dlist->data; | |
2982 dlist = dlist->next; | |
2983 | |
2984 name = filename_from_path(path); | |
2985 if (!name || | |
2986 (strcmp(name, THUMB_FOLDER_GLOBAL) != 0 && | |
2987 strcmp(name, THUMB_FOLDER_LOCAL) != 0 && | |
2988 strcmp(name, GQVIEW_CACHE_LOCAL_METADATA) != 0) ) | |
2989 { | |
2990 rlist = g_list_prepend(rlist, path); | |
2991 } | |
2992 } | |
2993 | |
2994 return g_list_reverse(rlist); | |
2995 } | |
2996 | |
2997 void file_util_delete_dir(const gchar *path, GtkWidget *parent) | |
2998 { | |
2999 GList *dlist = NULL; | |
3000 GList *flist = NULL; | |
3001 GList *rlist; | |
3002 | |
3003 if (!isdir(path)) return; | |
3004 | |
3005 if (islink(path)) | |
3006 { | |
3007 UtilityData *ud; | |
3008 gchar *text; | |
3009 | |
3010 ud = g_new0(UtilityData, 1); | |
3011 ud->type = UTILITY_TYPE_DELETE_LINK; | |
3012 ud->source_path = g_strdup(path); | |
3013 ud->dlist = NULL; | |
3014 ud->flist = NULL; | |
3015 | |
3016 ud->gd = file_util_gen_dlg(_("Delete folder"), "GQview", "dlg_confirm", | |
3017 parent, TRUE, | |
3018 file_util_delete_dir_cancel_cb, ud); | |
3019 | |
3020 text = g_strdup_printf(_("This will delete the symbolic link:\n\n%s\n\n" | |
3021 "The folder this link points to will not be deleted."), | |
3022 path); | |
3023 generic_dialog_add_message(ud->gd, GTK_STOCK_DIALOG_QUESTION, | |
3024 _("Delete symbolic link to folder?"), | |
3025 text); | |
3026 g_free(text); | |
3027 | |
3028 generic_dialog_add_button(ud->gd, GTK_STOCK_DELETE, NULL, file_util_delete_dir_ok_cb, TRUE); | |
3029 | |
3030 gtk_widget_show(ud->gd->dialog); | |
3031 | |
3032 return; | |
3033 } | |
3034 | |
3035 if (!access_file(path, W_OK | X_OK)) | |
3036 { | |
3037 gchar *text; | |
3038 | |
3039 text = g_strdup_printf(_("Unable to remove folder %s\n" | |
3040 "Permissions do not allow writing to the folder."), path); | |
3041 file_util_warning_dialog(_("Delete failed"), text, GTK_STOCK_DIALOG_ERROR, parent); | |
3042 g_free(text); | |
3043 | |
3044 return; | |
3045 } | |
3046 | |
3047 if (!path_list_lstat(path, &flist, &dlist)) | |
3048 { | |
3049 gchar *text; | |
3050 | |
3051 text = g_strdup_printf(_("Unable to list contents of folder %s"), path); | |
3052 file_util_warning_dialog(_("Delete failed"), text, GTK_STOCK_DIALOG_ERROR, parent); | |
3053 g_free(text); | |
3054 | |
3055 return; | |
3056 } | |
3057 | |
3058 rlist = file_util_delete_dir_remaining_folders(dlist); | |
3059 if (rlist) | |
3060 { | |
3061 GenericDialog *gd; | |
3062 GtkWidget *box; | |
3063 gchar *text; | |
3064 | |
3065 gd = file_util_gen_dlg(_("Folder contains subfolders"), "GQview", "dlg_warning", | |
3066 parent, TRUE, NULL, NULL); | |
3067 generic_dialog_add_button(gd, GTK_STOCK_CLOSE, NULL, NULL, TRUE); | |
3068 | |
3069 text = g_strdup_printf(_("Unable to delete the folder:\n\n%s\n\n" | |
3070 "This folder contains subfolders which must be moved before it can be deleted."), | |
3071 path); | |
3072 box = generic_dialog_add_message(gd, GTK_STOCK_DIALOG_WARNING, | |
3073 _("Folder contains subfolders"), | |
3074 text); | |
3075 g_free(text); | |
3076 | |
3077 box = pref_group_new(box, TRUE, _("Subfolders:"), GTK_ORIENTATION_VERTICAL); | |
3078 | |
3079 rlist = path_list_sort(rlist); | |
3080 file_util_dialog_add_list(box, rlist, FALSE); | |
3081 | |
3082 gtk_widget_show(gd->dialog); | |
3083 } | |
3084 else | |
3085 { | |
3086 UtilityData *ud; | |
3087 GtkWidget *box; | |
3088 GtkWidget *view; | |
3089 GtkTreeSelection *selection; | |
3090 gchar *text; | |
3091 | |
3092 ud = g_new0(UtilityData, 1); | |
3093 ud->type = UTILITY_TYPE_DELETE_FOLDER; | |
3094 ud->source_path = g_strdup(path); | |
3095 ud->dlist = dlist; | |
3096 dlist = NULL; | |
3097 ud->flist = path_list_sort(flist); | |
3098 flist = NULL; | |
3099 | |
3100 ud->gd = file_util_gen_dlg(_("Delete folder"), "GQview", "dlg_confirm", | |
3101 parent, TRUE, file_util_delete_dir_cancel_cb, ud); | |
3102 generic_dialog_add_button(ud->gd, GTK_STOCK_DELETE, NULL, file_util_delete_dir_ok_cb, TRUE); | |
3103 | |
3104 text = g_strdup_printf(_("This will delete the folder:\n\n%s\n\n" | |
3105 "The contents of this folder will also be deleted."), | |
3106 path); | |
3107 box = generic_dialog_add_message(ud->gd, GTK_STOCK_DIALOG_QUESTION, | |
3108 _("Delete folder?"), | |
3109 text); | |
3110 g_free(text); | |
3111 | |
3112 box = pref_group_new(box, TRUE, _("Contents:"), GTK_ORIENTATION_HORIZONTAL); | |
3113 | |
3114 view = file_util_dialog_add_list(box, ud->flist, FALSE); | |
3115 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); | |
3116 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); | |
3117 gtk_tree_selection_set_select_function(selection, file_util_delete_dir_preview_cb, ud, NULL); | |
3118 | |
3119 generic_dialog_add_image(ud->gd, box, NULL, NULL, NULL, NULL, FALSE); | |
3120 | |
3121 box_append_safe_delete_status(ud->gd); | |
3122 | |
3123 gtk_widget_show(ud->gd->dialog); | |
3124 } | |
3125 | |
3126 g_list_free(rlist); | |
3127 path_list_free(dlist); | |
3128 path_list_free(flist); | |
3129 } | |
3130 |