Include debug.h from main.h since debug macros may be used anywhere in the code.
[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 "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         gint sorted = FALSE;
37         gint warned = FALSE;
38
39         if (!filelist_read(options->file_ops.safe_delete_path, &list, NULL)) return 0;
40
41         work = list;
42         while (work)
43                 {
44                 FileData *fd;
45                 gint v;
46
47                 fd = work->data;
48                 work = work->next;
49
50                 v = (gint)strtol(fd->name, NULL, 10);
51                 if (v >= n) n = v + 1;
52
53                 total += fd->size;
54                 }
55
56         while (options->file_ops.safe_delete_folder_maxsize > 0 && list &&
57                (free_space < 0 || total + free_space > (gint64)options->file_ops.safe_delete_folder_maxsize * 1048576) )
58                 {
59                 FileData *fd;
60
61                 if (!sorted)
62                         {
63                         list = filelist_sort(list, SORT_NAME, TRUE);
64                         sorted = TRUE;
65                         }
66
67                 fd = list->data;
68                 list = g_list_remove(list, fd);
69
70                 DEBUG_1("expunging from trash for space: %s", fd->name);
71                 if (!unlink_file(fd->path) && !warned)
72                         {
73                         file_util_warning_dialog(_("Delete failed"),
74                                                  _("Unable to remove old file from trash folder"),
75                                                  GTK_STOCK_DIALOG_WARNING, NULL);
76                         warned = TRUE;
77                         }
78                 total -= fd->size;
79                 file_data_unref(fd);
80                 }
81
82         filelist_free(list);
83
84         return n;
85 }
86
87 void file_util_trash_clear(void)
88 {
89         file_util_safe_number(-1);
90 }
91
92 static gchar *file_util_safe_dest(const gchar *path)
93 {
94         gint n;
95
96         n = file_util_safe_number(filesize(path));
97         return g_strdup_printf("%s/%06d_%s", options->file_ops.safe_delete_path, n, filename_from_path(path));
98 }
99
100 static void file_util_safe_del_toggle_cb(GtkWidget *button, gpointer data)
101 {
102         options->file_ops.safe_delete_enable = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
103 }
104
105 static void file_util_safe_del_close_cb(GtkWidget *dialog, gpointer data)
106 {
107         GenericDialog **gd = data;
108
109         *gd = NULL;
110 }
111
112 gint file_util_safe_unlink(const gchar *path)
113 {
114         static GenericDialog *gd = NULL;
115         gchar *result = NULL;
116         gint success = TRUE;
117
118         if (!isfile(path)) return FALSE;
119
120         if (!isdir(options->file_ops.safe_delete_path))
121                 {
122                 DEBUG_1("creating trash: %s", options->file_ops.safe_delete_path);
123                 if (!options->file_ops.safe_delete_path || !mkdir_utf8(options->file_ops.safe_delete_path, 0755))
124                         {
125                         result = _("Could not create folder");
126                         success = FALSE;
127                         }
128                 }
129
130         if (success)
131                 {
132                 gchar *dest;
133
134                 dest = file_util_safe_dest(path);
135                 if (dest)
136                         {
137                         DEBUG_1("safe deleting %s to %s", path, dest);
138                         success = move_file(path, dest);
139                         }
140                 else
141                         {
142                         success = FALSE;
143                         }
144
145                 if (!success && !access_file(path, W_OK))
146                         {
147                         result = _("Permission denied");
148                         }
149                 g_free(dest);
150                 }
151
152         if (result && !gd)
153                 {
154                 GtkWidget *button;
155                 gchar *buf;
156
157                 buf = g_strdup_printf(_("Unable to access or create the trash folder.\n\"%s\""), options->file_ops.safe_delete_path);
158                 gd = file_util_warning_dialog(result, buf, GTK_STOCK_DIALOG_WARNING, NULL);
159                 g_free(buf);
160
161                 button = gtk_check_button_new_with_label(_("Turn off safe delete"));
162                 g_signal_connect(G_OBJECT(button), "toggled",
163                                  G_CALLBACK(file_util_safe_del_toggle_cb), NULL);
164                 gtk_box_pack_start(GTK_BOX(gd->vbox), button, FALSE, FALSE, 0);
165                 gtk_widget_show(button);
166
167                 g_signal_connect(G_OBJECT(gd->dialog), "destroy",
168                                  G_CALLBACK(file_util_safe_del_close_cb), &gd);
169                 }
170
171         return success;
172 }
173
174 gchar *file_util_safe_delete_status(void)
175 {
176         gchar *buf;
177
178         if (options->editor_command[CMD_DELETE])
179                 {
180                 buf = g_strdup(_("Deletion by external command"));
181                 }
182         else
183                 {
184                 if (options->file_ops.safe_delete_enable)
185                         {
186                         gchar *buf2;
187                         if (options->file_ops.safe_delete_folder_maxsize > 0)
188                                 buf2 = g_strdup_printf(_(" (max. %d MB)"), options->file_ops.safe_delete_folder_maxsize);
189                         else
190                                 buf2 = g_strdup("");
191
192                         buf = g_strdup_printf(_("Safe delete: %s%s\nTrash: %s"), _("on"), buf2, options->file_ops.safe_delete_path);
193                         g_free(buf2);
194                         }
195                 else
196                         {
197                         buf = g_strdup_printf(_("Safe delete: %s"), _("off"));
198                         }
199                 }
200                 
201         return buf;
202 }