Fix untranslated text
[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 <unistd.h>
25
26 #include <cstdlib>
27
28 #include <gio/gio.h>
29
30 #include "debug.h"
31 #include "editors.h"
32 #include "filedata.h"
33 #include "intl.h"
34 #include "main-defines.h"
35 #include "options.h"
36 #include "typedefs.h"
37 #include "ui-fileops.h"
38 #include "ui-utildlg.h"
39 #include "utilops.h"
40 #include "window.h"
41
42 /*
43  *--------------------------------------------------------------------------
44  * Safe Delete
45  *--------------------------------------------------------------------------
46  */
47
48 static gint file_util_safe_number(gint64 free_space)
49 {
50         gint n = 0;
51         gint64 total = 0;
52         GList *list;
53         GList *work;
54         gboolean sorted = FALSE;
55         gboolean warned = FALSE;
56         FileData *dir_fd;
57
58         dir_fd = file_data_new_dir(options->file_ops.safe_delete_path);
59         if (!filelist_read(dir_fd, &list, nullptr))
60                 {
61                 file_data_unref(dir_fd);
62                 return 0;
63                 }
64         file_data_unref(dir_fd);
65
66         work = list;
67         while (work)
68                 {
69                 FileData *fd;
70                 gint v;
71
72                 fd = static_cast<FileData *>(work->data);
73                 work = work->next;
74
75                 v = static_cast<gint>(strtol(fd->name, nullptr, 10));
76                 if (v >= n) n = v + 1;
77
78                 total += fd->size;
79                 }
80
81         while (options->file_ops.safe_delete_folder_maxsize > 0 && list &&
82                (free_space < 0 || total + free_space > static_cast<gint64>(options->file_ops.safe_delete_folder_maxsize) * 1048576) )
83                 {
84                 FileData *fd;
85
86                 if (!sorted)
87                         {
88                         list = filelist_sort(list, SORT_NAME, TRUE, TRUE);
89                         sorted = TRUE;
90                         }
91
92                 fd = static_cast<FileData *>(list->data);
93                 list = g_list_remove(list, fd);
94
95                 DEBUG_1("expunging from trash for space: %s", fd->name);
96                 if (!unlink_file(fd->path) && !warned)
97                         {
98                         file_util_warning_dialog(_("Delete failed"),
99                                                  _("Unable to remove old file from trash folder"),
100                                                  GQ_ICON_DIALOG_WARNING, nullptr);
101                         warned = TRUE;
102                         }
103                 total -= fd->size;
104                 file_data_unref(fd);
105                 }
106
107         filelist_free(list);
108
109         return n;
110 }
111
112 void file_util_trash_clear()
113 {
114         file_util_safe_number(-1);
115 }
116
117 static gchar *file_util_safe_dest(const gchar *path)
118 {
119         gint n;
120         gchar *name;
121         gchar *dest;
122
123         n = file_util_safe_number(filesize(path));
124         name = g_strdup_printf("%06d_%s", n, filename_from_path(path));
125         dest = g_build_filename(options->file_ops.safe_delete_path, name, NULL);
126         g_free(name);
127
128         return dest;
129 }
130
131 static void move_to_trash_failed_cb(GenericDialog *, gpointer)
132 {
133         help_window_show("TrashFailed.html");
134 }
135
136 gboolean file_util_safe_unlink(const gchar *path)
137 {
138         static GenericDialog *gd = nullptr;
139         gchar *result = nullptr;
140         gboolean success = TRUE;
141         gchar *message;
142
143         if (!isfile(path)) return FALSE;
144
145         if (options->file_ops.no_trash)
146                 {
147                 if (!unlink_file(path))
148                         {
149                         file_util_warning_dialog(_("Delete failed"),
150                                                  _("Unable to remove file"),
151                                                  GQ_ICON_DIALOG_WARNING, nullptr);
152                         success = FALSE;
153                         }
154                 }
155         else if (!options->file_ops.use_system_trash)
156                 {
157                 if (!isdir(options->file_ops.safe_delete_path))
158                         {
159                         DEBUG_1("creating trash: %s", options->file_ops.safe_delete_path);
160                         if (!options->file_ops.safe_delete_path || !mkdir_utf8(options->file_ops.safe_delete_path, 0755))
161                                 {
162                                 result = _("Could not create folder");
163                                 success = FALSE;
164                                 }
165                         }
166
167                 if (success)
168                         {
169                         gchar *dest;
170
171                         dest = file_util_safe_dest(path);
172                         if (dest)
173                                 {
174                                 DEBUG_1("safe deleting %s to %s", path, dest);
175                                 success = move_file(path, dest);
176                                 }
177                         else
178                                 {
179                                 success = FALSE;
180                                 }
181
182                         if (!success && !access_file(path, W_OK))
183                                 {
184                                 result = _("Permission denied");
185                                 }
186                         g_free(dest);
187                         }
188
189                 if (result && !gd)
190                         {
191                         gchar *buf;
192
193                         buf = g_strdup_printf(_("Unable to access or create the trash folder.\n\"%s\""), options->file_ops.safe_delete_path);
194                         gd = file_util_warning_dialog(result, buf, GQ_ICON_DIALOG_WARNING, nullptr);
195                         g_free(buf);
196                         }
197                 }
198         else
199                 {
200                 GFile *tmp = g_file_new_for_path(path);
201                 GError *error = nullptr;
202
203                 if (!g_file_trash(tmp, FALSE, &error) )
204                         {
205                         message = g_strconcat("See the Help file for a possible workaround.\n\n", error->message, NULL);
206                         gd = warning_dialog(_("Move to trash failed\n\n"), message, GQ_ICON_DIALOG_ERROR, nullptr);
207                         generic_dialog_add_button(gd, GQ_ICON_HELP, _("Help"), move_to_trash_failed_cb, FALSE);
208
209                         g_free(message);
210                         g_error_free(error);
211
212                         /* A second warning dialog is not necessary */
213                         }
214         }
215
216         return success;
217 }
218
219 gchar *file_util_safe_delete_status()
220 {
221         gchar *buf = nullptr;
222
223         if (is_valid_editor_command(CMD_DELETE))
224                 {
225                 buf = g_strdup(_("Deletion by external command"));
226                 }
227         else if (options->file_ops.no_trash)
228                 {
229                 buf = g_strdup(_("Deleting without trash"));
230                 }
231         else if (options->file_ops.safe_delete_enable)
232                 {
233                 if (!options->file_ops.use_system_trash)
234                         {
235                         gchar *buf2;
236                         if (options->file_ops.safe_delete_folder_maxsize > 0)
237                                 buf2 = g_strdup_printf(_(" (max. %d MiB)"), options->file_ops.safe_delete_folder_maxsize);
238                         else
239                                 buf2 = g_strdup("");
240
241                         buf = g_strdup_printf(_("Using Geeqie Trash bin\n%s"), buf2);
242                         g_free(buf2);
243                         }
244                 else
245                         {
246                         buf = g_strdup(_("Using system Trash bin"));
247                         }
248                 }
249
250         return buf;
251 }
252 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */