moved safe delete functions to separate file
[geeqie.git] / src / trash.c
1 /*
2  * Geeqie
3  * (C) 2006 John Ellis
4  * Copyright (C) 2008 The Geeqie Team
5  *
6  * Author: John Ellis
7  *
8  * This software is released under the GNU General Public License (GNU GPL).
9  * Please read the included file COPYING for more information.
10  * This software comes with no warranty of any kind, use at your own risk!
11  */
12
13
14 #include "main.h"
15 #include "trash.h"
16 #include "utilops.h"
17
18
19 #include "debug.h"
20 #include "filedata.h"
21 #include "ui_fileops.h"
22 #include "ui_misc.h"
23
24
25 /*
26  *--------------------------------------------------------------------------
27  * Safe Delete
28  *--------------------------------------------------------------------------
29  */
30
31 static gint file_util_safe_number(gint64 free_space)
32 {
33         gint n = 0;
34         gint64 total = 0;
35         GList *list;
36         GList *work;
37         gint sorted = FALSE;
38         gint warned = FALSE;
39
40         if (!filelist_read(options->file_ops.safe_delete_path, &list, NULL)) return 0;
41
42         work = list;
43         while (work)
44                 {
45                 FileData *fd;
46                 gint v;
47
48                 fd = work->data;
49                 work = work->next;
50
51                 v = (gint)strtol(fd->name, NULL, 10);
52                 if (v >= n) n = v + 1;
53
54                 total += fd->size;
55                 }
56
57         while (options->file_ops.safe_delete_folder_maxsize > 0 && list &&
58                (free_space < 0 || total + free_space > (gint64)options->file_ops.safe_delete_folder_maxsize * 1048576) )
59                 {
60                 FileData *fd;
61
62                 if (!sorted)
63                         {
64                         list = filelist_sort(list, SORT_NAME, TRUE);
65                         sorted = TRUE;
66                         }
67
68                 fd = list->data;
69                 list = g_list_remove(list, fd);
70
71                 DEBUG_1("expunging from trash for space: %s", fd->name);
72                 if (!unlink_file(fd->path) && !warned)
73                         {
74                         file_util_warning_dialog(_("Delete failed"),
75                                                  _("Unable to remove old file from trash folder"),
76                                                  GTK_STOCK_DIALOG_WARNING, NULL);
77                         warned = TRUE;
78                         }
79                 total -= fd->size;
80                 file_data_unref(fd);
81                 }
82
83         filelist_free(list);
84
85         return n;
86 }
87
88 void file_util_trash_clear(void)
89 {
90         file_util_safe_number(-1);
91 }
92
93 static gchar *file_util_safe_dest(const gchar *path)
94 {
95         gint n;
96
97         n = file_util_safe_number(filesize(path));
98         return g_strdup_printf("%s/%06d_%s", options->file_ops.safe_delete_path, n, filename_from_path(path));
99 }
100
101 static void file_util_safe_del_toggle_cb(GtkWidget *button, gpointer data)
102 {
103         options->file_ops.safe_delete_enable = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
104 }
105
106 static void file_util_safe_del_close_cb(GtkWidget *dialog, gpointer data)
107 {
108         GenericDialog **gd = data;
109
110         *gd = NULL;
111 }
112
113 gint file_util_safe_unlink(const char *path)
114 {
115         static GenericDialog *gd = NULL;
116         gchar *result = NULL;
117         gint success = TRUE;
118
119         if (!isfile(path)) return FALSE;
120
121         if (!isdir(options->file_ops.safe_delete_path))
122                 {
123                 DEBUG_1("creating trash: %s", options->file_ops.safe_delete_path);
124                 if (!options->file_ops.safe_delete_path || !mkdir_utf8(options->file_ops.safe_delete_path, 0755))
125                         {
126                         result = _("Could not create folder");
127                         success = FALSE;
128                         }
129                 }
130
131         if (success)
132                 {
133                 gchar *dest;
134
135                 dest = file_util_safe_dest(path);
136                 if (dest)
137                         {
138                         DEBUG_1("safe deleting %s to %s", path, dest);
139                         success = move_file(path, dest);
140                         }
141                 else
142                         {
143                         success = FALSE;
144                         }
145
146                 if (!success && !access_file(path, W_OK))
147                         {
148                         result = _("Permission denied");
149                         }
150                 g_free(dest);
151                 }
152
153         if (result && !gd)
154                 {
155                 GtkWidget *button;
156                 gchar *buf;
157
158                 buf = g_strdup_printf(_("Unable to access or create the trash folder.\n\"%s\""), options->file_ops.safe_delete_path);
159                 gd = file_util_warning_dialog(result, buf, GTK_STOCK_DIALOG_WARNING, NULL);
160                 g_free(buf);
161
162                 button = gtk_check_button_new_with_label(_("Turn off safe delete"));
163                 g_signal_connect(G_OBJECT(button), "toggled",
164                                  G_CALLBACK(file_util_safe_del_toggle_cb), NULL);
165                 gtk_box_pack_start(GTK_BOX(gd->vbox), button, FALSE, FALSE, 0);
166                 gtk_widget_show(button);
167
168                 g_signal_connect(G_OBJECT(gd->dialog), "destroy",
169                                  G_CALLBACK(file_util_safe_del_close_cb), &gd);
170                 }
171
172         return success;
173 }
174
175 char *file_util_safe_delete_status(void)
176 {
177         gchar *buf;
178
179         if (options->editor_command[CMD_DELETE])
180                 {
181                 buf = g_strdup(_("Deletion by external command"));
182                 }
183         else
184                 {
185                 if (options->file_ops.safe_delete_enable)
186                         {
187                         gchar *buf2;
188                         if (options->file_ops.safe_delete_folder_maxsize > 0)
189                                 buf2 = g_strdup_printf(_(" (max. %d MB)"), options->file_ops.safe_delete_folder_maxsize);
190                         else
191                                 buf2 = g_strdup("");
192
193                         buf = g_strdup_printf(_("Safe delete: %s%s\nTrash: %s"), _("on"), buf2, options->file_ops.safe_delete_path);
194                         g_free(buf2);
195                         }
196                 else
197                         {
198                         buf = g_strdup_printf(_("Safe delete: %s"), _("off"));
199                         }
200                 }
201                 
202         return buf;
203 }
204