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