1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3 /* fm-error-reporting.h - implementation of file manager functions that report
4 errors to the user.
5
6 Copyright (C) 2000 Eazel, Inc.
7
8 The Mate Library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version.
12
13 The Mate Library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
17
18 You should have received a copy of the GNU Library General Public
19 License along with the Mate Library; see the file COPYING.LIB. If not,
20 write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21 Boston, MA 02110-1301, USA.
22
23 Authors: John Sullivan <sullivan@eazel.com>
24 */
25
26 #include <config.h>
27 #include <string.h>
28
29 #include <glib/gi18n.h>
30
31 #include <eel/eel-string.h>
32 #include <eel/eel-stock-dialogs.h>
33
34 #include <libcaja-private/caja-debug-log.h>
35 #include <libcaja-private/caja-file.h>
36
37 #include "fm-error-reporting.h"
38
39 #define NEW_NAME_TAG "Caja: new name"
40 #define MAXIMUM_DISPLAYED_FILE_NAME_LENGTH 50
41
42 static void finish_rename (CajaFile *file, gboolean stop_timer, GError *error);
43
44 void
fm_report_error_loading_directory(CajaFile * file,GError * error,GtkWindow * parent_window)45 fm_report_error_loading_directory (CajaFile *file,
46 GError *error,
47 GtkWindow *parent_window)
48 {
49 char *file_name;
50 char *message;
51
52 if (error == NULL ||
53 error->message == NULL)
54 {
55 return;
56 }
57
58 if (error->domain == G_IO_ERROR &&
59 error->code == G_IO_ERROR_NOT_MOUNTED)
60 {
61 /* This case is retried automatically */
62 return;
63 }
64
65 file_name = caja_file_get_display_name (file);
66
67 if (error->domain == G_IO_ERROR)
68 {
69 switch (error->code)
70 {
71 case G_IO_ERROR_PERMISSION_DENIED:
72 message = g_strdup_printf (_("You do not have the permissions necessary to view the contents of \"%s\"."),
73 file_name);
74 break;
75 case G_IO_ERROR_NOT_FOUND:
76 message = g_strdup_printf (_("\"%s\" could not be found. Perhaps it has recently been deleted."),
77 file_name);
78 break;
79 default:
80 message = g_strdup_printf (_("Sorry, could not display all the contents of \"%s\": %s"), file_name,
81 error->message);
82 }
83 }
84 else
85 {
86 message = g_strdup (error->message);
87 }
88
89 eel_show_error_dialog (_("The folder contents could not be displayed."), message, parent_window);
90
91 g_free (file_name);
92 g_free (message);
93 }
94
95 void
fm_report_error_renaming_file(CajaFile * file,const char * new_name,GError * error,GtkWindow * parent_window)96 fm_report_error_renaming_file (CajaFile *file,
97 const char *new_name,
98 GError *error,
99 GtkWindow *parent_window)
100 {
101 char *original_name, *original_name_truncated;
102 char *new_name_truncated;
103 char *message;
104
105 /* Truncate names for display since very long file names with no spaces
106 * in them won't get wrapped, and can create insanely wide dialog boxes.
107 */
108 original_name = caja_file_get_display_name (file);
109 original_name_truncated = eel_str_middle_truncate (original_name, MAXIMUM_DISPLAYED_FILE_NAME_LENGTH);
110 g_free (original_name);
111
112 new_name_truncated = eel_str_middle_truncate (new_name, MAXIMUM_DISPLAYED_FILE_NAME_LENGTH);
113
114 message = NULL;
115 if (error->domain == G_IO_ERROR)
116 {
117 switch (error->code)
118 {
119 case G_IO_ERROR_EXISTS:
120 message = g_strdup_printf (_("The name \"%s\" is already used in this folder. "
121 "Please use a different name."),
122 new_name_truncated);
123 break;
124 case G_IO_ERROR_NOT_FOUND:
125 message = g_strdup_printf (_("There is no \"%s\" in this folder. "
126 "Perhaps it was just moved or deleted?"),
127 original_name_truncated);
128 break;
129 case G_IO_ERROR_PERMISSION_DENIED:
130 message = g_strdup_printf (_("You do not have the permissions necessary to rename \"%s\"."),
131 original_name_truncated);
132 break;
133 case G_IO_ERROR_INVALID_FILENAME:
134 if (strchr (new_name, '/') != NULL)
135 {
136 message = g_strdup_printf (_("The name \"%s\" is not valid because it contains the character \"/\". "
137 "Please use a different name."),
138 new_name_truncated);
139 }
140 else
141 {
142 message = g_strdup_printf (_("The name \"%s\" is not valid. "
143 "Please use a different name."),
144 new_name_truncated);
145 }
146 break;
147 default:
148 break;
149 }
150 }
151
152 if (message == NULL)
153 {
154 /* We should invent decent error messages for every case we actually experience. */
155 g_warning ("Hit unhandled case %s:%d in fm_report_error_renaming_file",
156 g_quark_to_string (error->domain), error->code);
157 /* fall through */
158 message = g_strdup_printf (_("Sorry, could not rename \"%s\" to \"%s\": %s"),
159 original_name_truncated, new_name_truncated,
160 error->message);
161 }
162
163 g_free (original_name_truncated);
164 g_free (new_name_truncated);
165
166 eel_show_error_dialog (_("The item could not be renamed."), message, parent_window);
167 g_free (message);
168 }
169
170 void
fm_report_error_setting_group(CajaFile * file,GError * error,GtkWindow * parent_window)171 fm_report_error_setting_group (CajaFile *file,
172 GError *error,
173 GtkWindow *parent_window)
174 {
175 char *file_name;
176 char *message;
177
178 if (error == NULL)
179 {
180 return;
181 }
182
183 file_name = caja_file_get_display_name (file);
184
185 message = NULL;
186 if (error->domain == G_IO_ERROR)
187 {
188 switch (error->code)
189 {
190 case G_IO_ERROR_PERMISSION_DENIED:
191 message = g_strdup_printf (_("You do not have the permissions necessary to change the group of \"%s\"."),
192 file_name);
193 break;
194 default:
195 break;
196 }
197 }
198
199 if (message == NULL)
200 {
201 /* We should invent decent error messages for every case we actually experience. */
202 g_warning ("Hit unhandled case %s:%d in fm_report_error_setting_group",
203 g_quark_to_string (error->domain), error->code);
204 /* fall through */
205 message = g_strdup_printf (_("Sorry, could not change the group of \"%s\": %s"), file_name,
206 error->message);
207 }
208
209
210 eel_show_error_dialog (_("The group could not be changed."), message, parent_window);
211
212 g_free (file_name);
213 g_free (message);
214 }
215
216 void
fm_report_error_setting_owner(CajaFile * file,GError * error,GtkWindow * parent_window)217 fm_report_error_setting_owner (CajaFile *file,
218 GError *error,
219 GtkWindow *parent_window)
220 {
221 char *file_name;
222 char *message;
223
224 if (error == NULL)
225 {
226 return;
227 }
228
229 file_name = caja_file_get_display_name (file);
230
231 message = g_strdup_printf (_("Sorry, could not change the owner of \"%s\": %s"), file_name, error->message);
232
233 eel_show_error_dialog (_("The owner could not be changed."), message, parent_window);
234
235 g_free (file_name);
236 g_free (message);
237 }
238
239 void
fm_report_error_setting_permissions(CajaFile * file,GError * error,GtkWindow * parent_window)240 fm_report_error_setting_permissions (CajaFile *file,
241 GError *error,
242 GtkWindow *parent_window)
243 {
244 char *file_name;
245 char *message;
246
247 if (error == NULL)
248 {
249 return;
250 }
251
252 file_name = caja_file_get_display_name (file);
253
254 message = g_strdup_printf (_("Sorry, could not change the permissions of \"%s\": %s"), file_name, error->message);
255
256 eel_show_error_dialog (_("The permissions could not be changed."), message, parent_window);
257
258 g_free (file_name);
259 g_free (message);
260 }
261
262 typedef struct _FMRenameData
263 {
264 char *name;
265 CajaFileOperationCallback callback;
266 gpointer callback_data;
267 } FMRenameData;
268
269 static void
fm_rename_data_free(FMRenameData * data)270 fm_rename_data_free (FMRenameData *data)
271 {
272 g_free (data->name);
273 g_free (data);
274 }
275
276 static void
rename_callback(CajaFile * file,GFile * result_location,GError * error,gpointer callback_data)277 rename_callback (CajaFile *file, GFile *result_location,
278 GError *error, gpointer callback_data)
279 {
280 FMRenameData *data;
281
282 g_assert (CAJA_IS_FILE (file));
283 g_assert (callback_data == NULL);
284
285 data = g_object_get_data (G_OBJECT (file), NEW_NAME_TAG);
286 g_assert (data != NULL);
287
288 if (error &&
289 !(error->domain == G_IO_ERROR && error->code == G_IO_ERROR_CANCELLED))
290 {
291 /* If rename failed, notify the user. */
292 fm_report_error_renaming_file (file, data->name, error, NULL);
293 }
294
295 finish_rename (file, TRUE, error);
296 }
297
298 static void
cancel_rename_callback(gpointer callback_data)299 cancel_rename_callback (gpointer callback_data)
300 {
301 GError *error;
302
303 error = g_error_new (G_IO_ERROR, G_IO_ERROR_CANCELLED, "Cancelled");
304 finish_rename (CAJA_FILE (callback_data), FALSE, error);
305 g_error_free (error);
306 }
307
308 static void
finish_rename(CajaFile * file,gboolean stop_timer,GError * error)309 finish_rename (CajaFile *file, gboolean stop_timer, GError *error)
310 {
311 FMRenameData *data;
312
313 data = g_object_get_data (G_OBJECT (file), NEW_NAME_TAG);
314 if (data == NULL)
315 {
316 return;
317 }
318
319 /* Cancel both the rename and the timed wait. */
320 caja_file_cancel (file, rename_callback, NULL);
321 if (stop_timer)
322 {
323 eel_timed_wait_stop (cancel_rename_callback, file);
324 }
325
326 if (data->callback != NULL)
327 {
328 data->callback (file, NULL, error, data->callback_data);
329 }
330
331 /* Let go of file name. */
332 g_object_set_data (G_OBJECT (file), NEW_NAME_TAG, NULL);
333 }
334
335 void
fm_rename_file(CajaFile * file,const char * new_name,CajaFileOperationCallback callback,gpointer callback_data)336 fm_rename_file (CajaFile *file,
337 const char *new_name,
338 CajaFileOperationCallback callback,
339 gpointer callback_data)
340 {
341 char *old_name, *wait_message;
342 FMRenameData *data;
343 char *uri;
344 GError *error;
345
346 g_return_if_fail (CAJA_IS_FILE (file));
347 g_return_if_fail (new_name != NULL);
348
349 /* Stop any earlier rename that's already in progress. */
350 error = g_error_new (G_IO_ERROR, G_IO_ERROR_CANCELLED, "Cancelled");
351 finish_rename (file, TRUE, error);
352 g_error_free (error);
353
354 data = g_new0 (FMRenameData, 1);
355 data->name = g_strdup (new_name);
356 data->callback = callback;
357 data->callback_data = callback_data;
358
359 /* Attach the new name to the file. */
360 g_object_set_data_full (G_OBJECT (file),
361 NEW_NAME_TAG,
362 data, (GDestroyNotify)fm_rename_data_free);
363
364 /* Start the timed wait to cancel the rename. */
365 old_name = caja_file_get_display_name (file);
366 wait_message = g_strdup_printf (_("Renaming \"%s\" to \"%s\"."),
367 old_name,
368 new_name);
369 g_free (old_name);
370 eel_timed_wait_start (cancel_rename_callback, file, wait_message,
371 NULL); /* FIXME bugzilla.gnome.org 42395: Parent this? */
372 g_free (wait_message);
373
374 uri = caja_file_get_uri (file);
375 caja_debug_log (FALSE, CAJA_DEBUG_LOG_DOMAIN_USER,
376 "rename file old=\"%s\", new=\"%s\"",
377 uri, new_name);
378 g_free (uri);
379
380 /* Start the rename. */
381 caja_file_rename (file, new_name,
382 rename_callback, NULL);
383 }
384