Use a struct to handle editor's properties.
[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         gchar *name;
96         gchar *dest;
97
98         n = file_util_safe_number(filesize(path));
99         name = g_strdup_printf("%06d_%s", n, filename_from_path(path));
100         dest = g_build_filename(options->file_ops.safe_delete_path, name, NULL);
101         g_free(name);
102
103         return dest;
104 }
105
106 static void file_util_safe_del_toggle_cb(GtkWidget *button, gpointer data)
107 {
108         options->file_ops.safe_delete_enable = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
109 }
110
111 static void file_util_safe_del_close_cb(GtkWidget *dialog, gpointer data)
112 {
113         GenericDialog **gd = data;
114
115         *gd = NULL;
116 }
117
118 gint file_util_safe_unlink(const gchar *path)
119 {
120         static GenericDialog *gd = NULL;
121         gchar *result = NULL;
122         gint success = TRUE;
123
124         if (!isfile(path)) return FALSE;
125
126         if (!isdir(options->file_ops.safe_delete_path))
127                 {
128                 DEBUG_1("creating trash: %s", options->file_ops.safe_delete_path);
129                 if (!options->file_ops.safe_delete_path || !mkdir_utf8(options->file_ops.safe_delete_path, 0755))
130                         {
131                         result = _("Could not create folder");
132                         success = FALSE;
133                         }
134                 }
135
136         if (success)
137                 {
138                 gchar *dest;
139
140                 dest = file_util_safe_dest(path);
141                 if (dest)
142                         {
143                         DEBUG_1("safe deleting %s to %s", path, dest);
144                         success = move_file(path, dest);
145                         }
146                 else
147                         {
148                         success = FALSE;
149                         }
150
151                 if (!success && !access_file(path, W_OK))
152                         {
153                         result = _("Permission denied");
154                         }
155                 g_free(dest);
156                 }
157
158         if (result && !gd)
159                 {
160                 GtkWidget *button;
161                 gchar *buf;
162
163                 buf = g_strdup_printf(_("Unable to access or create the trash folder.\n\"%s\""), options->file_ops.safe_delete_path);
164                 gd = file_util_warning_dialog(result, buf, GTK_STOCK_DIALOG_WARNING, NULL);
165                 g_free(buf);
166
167                 button = gtk_check_button_new_with_label(_("Turn off safe delete"));
168                 g_signal_connect(G_OBJECT(button), "toggled",
169                                  G_CALLBACK(file_util_safe_del_toggle_cb), NULL);
170                 gtk_box_pack_start(GTK_BOX(gd->vbox), button, FALSE, FALSE, 0);
171                 gtk_widget_show(button);
172
173                 g_signal_connect(G_OBJECT(gd->dialog), "destroy",
174                                  G_CALLBACK(file_util_safe_del_close_cb), &gd);
175                 }
176
177         return success;
178 }
179
180 gchar *file_util_safe_delete_status(void)
181 {
182         gchar *buf;
183
184         if (options->editor[CMD_DELETE].command)
185                 {
186                 buf = g_strdup(_("Deletion by external command"));
187                 }
188         else
189                 {
190                 if (options->file_ops.safe_delete_enable)
191                         {
192                         gchar *buf2;
193                         if (options->file_ops.safe_delete_folder_maxsize > 0)
194                                 buf2 = g_strdup_printf(_(" (max. %d MB)"), options->file_ops.safe_delete_folder_maxsize);
195                         else
196                                 buf2 = g_strdup("");
197
198                         buf = g_strdup_printf(_("Safe delete: %s%s\nTrash: %s"), _("on"), buf2, options->file_ops.safe_delete_path);
199                         g_free(buf2);
200                         }
201                 else
202                         {
203                         buf = g_strdup_printf(_("Safe delete: %s"), _("off"));
204                         }
205                 }
206                 
207         return buf;
208 }