Fix missing translation
[geeqie.git] / src / trash.cc
1 /*
2  * Copyright (C) 2006 John Ellis
3  * Copyright (C) 2008 - 2016 The Geeqie Team
4  *
5  * Author: John Ellis
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include "trash.h"
23
24 #include <config.h>
25
26 #include "utilops.h"
27 #include "window.h"
28
29 #include "debug.h"
30 #include "editors.h"
31 #include "filedata.h"
32 #include "intl.h"
33 #include "main-defines.h"
34 #include "options.h"
35 #include "ui-fileops.h"
36
37 /*
38  *--------------------------------------------------------------------------
39  * Safe Delete
40  *--------------------------------------------------------------------------
41  */
42
43 static gint file_util_safe_number(gint64 free_space)
44 {
45         gint n = 0;
46         gint64 total = 0;
47         GList *list;
48         GList *work;
49         gboolean sorted = FALSE;
50         gboolean warned = FALSE;
51         FileData *dir_fd;
52
53         dir_fd = file_data_new_dir(options->file_ops.safe_delete_path);
54         if (!filelist_read(dir_fd, &list, nullptr))
55                 {
56                 file_data_unref(dir_fd);
57                 return 0;
58                 }
59         file_data_unref(dir_fd);
60
61         work = list;
62         while (work)
63                 {
64                 FileData *fd;
65                 gint v;
66
67                 fd = static_cast<FileData *>(work->data);
68                 work = work->next;
69
70                 v = static_cast<gint>(strtol(fd->name, nullptr, 10));
71                 if (v >= n) n = v + 1;
72
73                 total += fd->size;
74                 }
75
76         while (options->file_ops.safe_delete_folder_maxsize > 0 && list &&
77                (free_space < 0 || total + free_space > static_cast<gint64>(options->file_ops.safe_delete_folder_maxsize) * 1048576) )
78                 {
79                 FileData *fd;
80
81                 if (!sorted)
82                         {
83                         list = filelist_sort(list, SORT_NAME, TRUE, TRUE);
84                         sorted = TRUE;
85                         }
86
87                 fd = static_cast<FileData *>(list->data);
88                 list = g_list_remove(list, fd);
89
90                 DEBUG_1("expunging from trash for space: %s", fd->name);
91                 if (!unlink_file(fd->path) && !warned)
92                         {
93                         file_util_warning_dialog(_("Delete failed"),
94                                                  _("Unable to remove old file from trash folder"),
95                                                  GQ_ICON_DIALOG_WARNING, nullptr);
96                         warned = TRUE;
97                         }
98                 total -= fd->size;
99                 file_data_unref(fd);
100                 }
101
102         filelist_free(list);
103
104         return n;
105 }
106
107 void file_util_trash_clear()
108 {
109         file_util_safe_number(-1);
110 }
111
112 static gchar *file_util_safe_dest(const gchar *path)
113 {
114         gint n;
115         gchar *name;
116         gchar *dest;
117
118         n = file_util_safe_number(filesize(path));
119         name = g_strdup_printf("%06d_%s", n, filename_from_path(path));
120         dest = g_build_filename(options->file_ops.safe_delete_path, name, NULL);
121         g_free(name);
122
123         return dest;
124 }
125
126 static void move_to_trash_failed_cb(GenericDialog *, gpointer)
127 {
128         help_window_show("TrashFailed.html");
129 }
130
131 gboolean file_util_safe_unlink(const gchar *path)
132 {
133         static GenericDialog *gd = nullptr;
134         gchar *result = nullptr;
135         gboolean success = TRUE;
136         gchar *message;
137
138         if (!isfile(path)) return FALSE;
139
140         if (options->file_ops.no_trash)
141                 {
142                 if (!unlink_file(path))
143                         {
144                         file_util_warning_dialog(_("Delete failed"),
145                                                  _("Unable to remove file"),
146                                                  GQ_ICON_DIALOG_WARNING, nullptr);
147                         success = FALSE;
148                         }
149                 }
150         else if (!options->file_ops.use_system_trash)
151                 {
152                 if (!isdir(options->file_ops.safe_delete_path))
153                         {
154                         DEBUG_1("creating trash: %s", options->file_ops.safe_delete_path);
155                         if (!options->file_ops.safe_delete_path || !mkdir_utf8(options->file_ops.safe_delete_path, 0755))
156                                 {
157                                 result = _("Could not create folder");
158                                 success = FALSE;
159                                 }
160                         }
161
162                 if (success)
163                         {
164                         gchar *dest;
165
166                         dest = file_util_safe_dest(path);
167                         if (dest)
168                                 {
169                                 DEBUG_1("safe deleting %s to %s", path, dest);
170                                 success = move_file(path, dest);
171                                 }
172                         else
173                                 {
174                                 success = FALSE;
175                                 }
176
177                         if (!success && !access_file(path, W_OK))
178                                 {
179                                 result = _("Permission denied");
180                                 }
181                         g_free(dest);
182                         }
183
184                 if (result && !gd)
185                         {
186                         gchar *buf;
187
188                         buf = g_strdup_printf(_("Unable to access or create the trash folder.\n\"%s\""), options->file_ops.safe_delete_path);
189                         gd = file_util_warning_dialog(result, buf, GQ_ICON_DIALOG_WARNING, nullptr);
190                         g_free(buf);
191                         }
192                 }
193         else
194                 {
195                 GFile *tmp = g_file_new_for_path(path);
196                 GError *error = nullptr;
197
198                 if (!g_file_trash(tmp, FALSE, &error) )
199                         {
200                         message = g_strconcat("See the Help file for a possible workaround.\n\n", error->message, NULL);
201                         gd = warning_dialog(_("Move to trash failed\n\n"), message, GQ_ICON_DIALOG_ERROR, nullptr);
202                         generic_dialog_add_button(gd, GQ_ICON_HELP, _("Help"), move_to_trash_failed_cb, FALSE);
203
204                         g_free(message);
205                         g_error_free(error);
206
207                         /* A second warning dialog is not necessary */
208                         }
209         }
210
211         return success;
212 }
213
214 gchar *file_util_safe_delete_status()
215 {
216         gchar *buf = nullptr;
217
218         if (is_valid_editor_command(CMD_DELETE))
219                 {
220                 buf = g_strdup(_("Deletion by external command"));
221                 }
222         else if (options->file_ops.no_trash)
223                 {
224                 buf = g_strdup(_("Deleting without trash"));
225                 }
226         else if (options->file_ops.safe_delete_enable)
227                 {
228                 if (!options->file_ops.use_system_trash)
229                         {
230                         gchar *buf2;
231                         if (options->file_ops.safe_delete_folder_maxsize > 0)
232                                 buf2 = g_strdup_printf(_(" (max. %d MiB)"), options->file_ops.safe_delete_folder_maxsize);
233                         else
234                                 buf2 = g_strdup("");
235
236                         buf = g_strdup_printf(_("Using Geeqie Trash bin\n%s"), buf2);
237                         g_free(buf2);
238                         }
239                 else
240                         {
241                         buf = g_strdup(_("Using system Trash bin"));
242                         }
243                 }
244
245         return buf;
246 }
247 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */