1 /*
2 * xed-io-error-info-bar.c
3 * This file is part of xed
4 *
5 * Copyright (C) 2005 - Paolo Maggi
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
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 */
22
23 /*
24 * Modified by the xed Team, 2005. See the AUTHORS file for a
25 * list of people on the xed Team.
26 * See the ChangeLog files for a list of changes.
27 *
28 * $Id$
29 */
30
31 /*
32 * Verbose error reporting for file I/O operations (load, save, revert, create)
33 */
34
35 #include <config.h>
36 #include <errno.h>
37 #include <string.h>
38 #include <glib/gi18n.h>
39 #include <gio/gio.h>
40 #include <xed/xed-encodings-combo-box.h>
41
42 #include "xed-settings.h"
43 #include "xed-utils.h"
44 #include "xed-document.h"
45 #include "xed-io-error-info-bar.h"
46
47 #define MAX_URI_IN_DIALOG_LENGTH 50
48
49 static gboolean
is_recoverable_error(const GError * error)50 is_recoverable_error (const GError *error)
51 {
52 gboolean is_recoverable = FALSE;
53
54 if (error->domain == G_IO_ERROR)
55 {
56 switch (error->code)
57 {
58 case G_IO_ERROR_PERMISSION_DENIED:
59 case G_IO_ERROR_NOT_FOUND:
60 case G_IO_ERROR_HOST_NOT_FOUND:
61 case G_IO_ERROR_TIMED_OUT:
62 case G_IO_ERROR_NOT_MOUNTABLE_FILE:
63 case G_IO_ERROR_NOT_MOUNTED:
64 case G_IO_ERROR_BUSY:
65 is_recoverable = TRUE;
66 }
67 }
68
69 return is_recoverable;
70 }
71
72 static gboolean
is_gio_error(const GError * error,gint code)73 is_gio_error (const GError *error,
74 gint code)
75 {
76 return error->domain == G_IO_ERROR && error->code == code;
77 }
78
79 static void
set_contents(GtkWidget * area,GtkWidget * contents)80 set_contents (GtkWidget *area,
81 GtkWidget *contents)
82 {
83 GtkWidget *content_area;
84
85 content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (area));
86 gtk_container_add (GTK_CONTAINER (content_area), contents);
87 }
88
89 static void
set_info_bar_text_and_icon(GtkWidget * info_bar,const gchar * icon_name,const gchar * primary_text,const gchar * secondary_text)90 set_info_bar_text_and_icon (GtkWidget *info_bar,
91 const gchar *icon_name,
92 const gchar *primary_text,
93 const gchar *secondary_text)
94 {
95 GtkWidget *hbox_content;
96 GtkWidget *image;
97 GtkWidget *vbox;
98 gchar *primary_markup;
99 gchar *secondary_markup;
100 GtkWidget *primary_label;
101 GtkWidget *secondary_label;
102
103 hbox_content = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
104
105 image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_DIALOG);
106 gtk_box_pack_start (GTK_BOX (hbox_content), image, FALSE, FALSE, 0);
107 gtk_widget_set_halign (image, GTK_ALIGN_CENTER);
108 gtk_widget_set_valign (image, GTK_ALIGN_START);
109
110 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
111 gtk_box_pack_start (GTK_BOX (hbox_content), vbox, TRUE, TRUE, 0);
112
113 primary_markup = g_strdup_printf ("<b>%s</b>", primary_text);
114 primary_label = gtk_label_new (primary_markup);
115 g_free (primary_markup);
116 gtk_box_pack_start (GTK_BOX (vbox), primary_label, TRUE, TRUE, 0);
117 gtk_label_set_use_markup (GTK_LABEL (primary_label), TRUE);
118 gtk_label_set_line_wrap (GTK_LABEL (primary_label), TRUE);
119 gtk_widget_set_halign (primary_label, GTK_ALIGN_START);
120 gtk_widget_set_can_focus (primary_label, TRUE);
121 gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE);
122
123 if (secondary_text != NULL)
124 {
125 secondary_markup = g_strdup_printf ("<small>%s</small>", secondary_text);
126 secondary_label = gtk_label_new (secondary_markup);
127 g_free (secondary_markup);
128 gtk_box_pack_start (GTK_BOX (vbox), secondary_label, TRUE, TRUE, 0);
129 gtk_widget_set_can_focus (secondary_label, TRUE);
130 gtk_label_set_use_markup (GTK_LABEL (secondary_label), TRUE);
131 gtk_label_set_line_wrap (GTK_LABEL (secondary_label), TRUE);
132 gtk_label_set_selectable (GTK_LABEL (secondary_label), TRUE);
133 gtk_widget_set_halign (secondary_label, GTK_ALIGN_START);
134 }
135
136 gtk_widget_show_all (hbox_content);
137 set_contents (info_bar, hbox_content);
138 }
139
140 static GtkWidget *
create_io_loading_error_info_bar(const gchar * primary_text,const gchar * secondary_text,gboolean recoverable_error)141 create_io_loading_error_info_bar (const gchar *primary_text,
142 const gchar *secondary_text,
143 gboolean recoverable_error)
144 {
145 GtkWidget *info_bar;
146
147 info_bar = gtk_info_bar_new_with_buttons (_("_Cancel"), GTK_RESPONSE_CANCEL, NULL);
148 gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar), GTK_MESSAGE_ERROR);
149
150 set_info_bar_text_and_icon (info_bar, "dialog-error-symbolic", primary_text, secondary_text);
151
152 if (recoverable_error)
153 {
154 gtk_info_bar_add_button (GTK_INFO_BAR (info_bar), _("_Retry"), GTK_RESPONSE_OK);
155 }
156
157 return info_bar;
158 }
159
160 static gboolean
parse_gio_error(gint code,gchar ** error_message,gchar ** message_details,GFile * location,const gchar * uri_for_display)161 parse_gio_error (gint code,
162 gchar **error_message,
163 gchar **message_details,
164 GFile *location,
165 const gchar *uri_for_display)
166 {
167 gboolean ret = TRUE;
168
169 switch (code)
170 {
171 case G_IO_ERROR_NOT_FOUND:
172 case G_IO_ERROR_NOT_DIRECTORY:
173 *error_message = g_strdup_printf (_("Could not find the file %s."), uri_for_display);
174 *message_details = g_strdup (_("Please check that you typed the "
175 "location correctly and try again."));
176 break;
177 case G_IO_ERROR_NOT_SUPPORTED:
178 {
179 gchar *scheme_string;
180 gchar *scheme_markup;
181
182 scheme_string = g_file_get_uri_scheme (location);
183
184 if ((scheme_string != NULL) && g_utf8_validate (scheme_string, -1, NULL))
185 {
186 scheme_markup = g_markup_printf_escaped ("<i>%s:</i>", scheme_string);
187
188 /* Translators: %s is a URI scheme (like for example http:, ftp:, etc.) */
189 *message_details = g_strdup_printf (_("xed cannot handle %s locations."), scheme_markup);
190 g_free (scheme_markup);
191 }
192 else
193 {
194 *message_details = g_strdup (_("xed cannot handle this location."));
195 }
196
197 g_free (scheme_string);
198 }
199 break;
200 case G_IO_ERROR_NOT_MOUNTABLE_FILE:
201 *message_details = g_strdup (_("The location of the file cannot be mounted."));
202 break;
203 case G_IO_ERROR_NOT_MOUNTED:
204 *message_details = g_strdup( _("The location of the file cannot be accessed because it is not mounted."));
205 break;
206 case G_IO_ERROR_IS_DIRECTORY:
207 *error_message = g_strdup_printf (_("%s is a directory."), uri_for_display);
208 *message_details = g_strdup (_("Please check that you typed the "
209 "location correctly and try again."));
210 break;
211 case G_IO_ERROR_INVALID_FILENAME:
212 *error_message = g_strdup_printf (_("%s is not a valid location."), uri_for_display);
213 *message_details = g_strdup (_("Please check that you typed the "
214 "location correctly and try again."));
215 break;
216 case G_IO_ERROR_HOST_NOT_FOUND:
217 /* This case can be hit for user-typed strings like "foo" due to
218 * the code that guesses web addresses when there's no initial "/".
219 * But this case is also hit for legitimate web addresses when
220 * the proxy is set up wrong.
221 */
222 {
223 gchar *hn = NULL;
224 gchar *uri;
225
226 uri = g_file_get_uri (location);
227
228 if (uri && xed_utils_decode_uri (uri, NULL, NULL, &hn, NULL, NULL))
229 {
230 if (hn != NULL)
231 {
232 gchar *host_markup;
233 gchar *host_name;
234
235 host_name = xed_utils_make_valid_utf8 (hn);
236 g_free (hn);
237
238 host_markup = g_markup_printf_escaped ("<i>%s</i>", host_name);
239 g_free (host_name);
240
241 /* Translators: %s is a host name */
242 *message_details = g_strdup_printf (_("Host %s could not be found. "
243 "Please check that your proxy settings "
244 "are correct and try again."),
245 host_markup);
246
247 g_free (host_markup);
248 }
249 }
250
251 g_free (uri);
252
253 if (!*message_details)
254 {
255 /* use the same string as INVALID_HOST */
256 *message_details = g_strdup_printf (_("Hostname was invalid. "
257 "Please check that you typed the location "
258 "correctly and try again."));
259 }
260 }
261 break;
262 case G_IO_ERROR_NOT_REGULAR_FILE:
263 *message_details = g_strdup_printf (_("%s is not a regular file."), uri_for_display);
264 break;
265 case G_IO_ERROR_TIMED_OUT:
266 *message_details = g_strdup (_("Connection timed out. Please try again."));
267 break;
268 default:
269 ret = FALSE;
270 break;
271 }
272
273 return ret;
274 }
275
276 static void
parse_error(const GError * error,gchar ** error_message,gchar ** message_details,GFile * location,const gchar * uri_for_display)277 parse_error (const GError *error,
278 gchar **error_message,
279 gchar **message_details,
280 GFile *location,
281 const gchar *uri_for_display)
282 {
283 gboolean ret = FALSE;
284
285 if (error->domain == G_IO_ERROR)
286 {
287 ret = parse_gio_error (error->code, error_message, message_details, location, uri_for_display);
288 }
289
290 if (!ret)
291 {
292 g_warning ("Hit unhandled case %d (%s) in %s.", error->code, error->message, G_STRFUNC);
293 *message_details = g_strdup_printf (_("Unexpected error: %s"), error->message);
294 }
295 }
296
297 GtkWidget *
xed_unrecoverable_reverting_error_info_bar_new(GFile * location,const GError * error)298 xed_unrecoverable_reverting_error_info_bar_new (GFile *location,
299 const GError *error)
300 {
301 gchar *error_message = NULL;
302 gchar *message_details = NULL;
303 gchar *full_formatted_uri;
304 gchar *uri_for_display;
305 gchar *temp_uri_for_display;
306 GtkWidget *info_bar;
307
308 g_return_val_if_fail (G_IS_FILE (location), NULL);
309 g_return_val_if_fail (error != NULL, NULL);
310 g_return_val_if_fail ((error->domain == GTK_SOURCE_FILE_LOADER_ERROR) || error->domain == G_IO_ERROR, NULL);
311
312 full_formatted_uri = g_file_get_parse_name (location);
313
314 /* Truncate the URI so it doesn't get insanely wide. Note that even
315 * though the dialog uses wrapped text, if the URI doesn't contain
316 * white space then the text-wrapping code is too stupid to wrap it.
317 */
318 temp_uri_for_display = xed_utils_str_middle_truncate (full_formatted_uri, MAX_URI_IN_DIALOG_LENGTH);
319 g_free (full_formatted_uri);
320
321 uri_for_display = g_markup_printf_escaped ("<i>%s</i>", temp_uri_for_display);
322 g_free (temp_uri_for_display);
323
324 if (is_gio_error (error, G_IO_ERROR_NOT_FOUND))
325 {
326 message_details = g_strdup (_("xed cannot find the file. "
327 "Perhaps it has recently been deleted."));
328 }
329 else
330 {
331 parse_error (error, &error_message, &message_details, location, uri_for_display);
332 }
333
334 if (error_message == NULL)
335 {
336 error_message = g_strdup_printf (_("Could not revert the file %s."), uri_for_display);
337 }
338
339 info_bar = create_io_loading_error_info_bar (error_message, message_details, FALSE);
340
341 g_free (uri_for_display);
342 g_free (error_message);
343 g_free (message_details);
344
345 return info_bar;
346 }
347
348 static void
create_combo_box(GtkWidget * info_bar,GtkWidget * vbox)349 create_combo_box (GtkWidget *info_bar,
350 GtkWidget *vbox)
351 {
352 GtkWidget *hbox;
353 GtkWidget *label;
354 GtkWidget *menu;
355 gchar *label_markup;
356
357 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
358
359 label_markup = g_strdup_printf ("<small>%s</small>", _("Ch_aracter Encoding:"));
360 label = gtk_label_new_with_mnemonic (label_markup);
361 g_free (label_markup);
362 gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
363 menu = xed_encodings_combo_box_new (TRUE);
364 g_object_set_data (G_OBJECT (info_bar), "xed-info-bar-encoding-menu", menu);
365
366 gtk_label_set_mnemonic_widget (GTK_LABEL (label), menu);
367 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
368 gtk_box_pack_start (GTK_BOX (hbox), menu, FALSE, FALSE, 0);
369
370 gtk_widget_show_all (hbox);
371 gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
372 }
373
374 static GtkWidget *
create_conversion_error_info_bar(const gchar * primary_text,const gchar * secondary_text,gboolean edit_anyway)375 create_conversion_error_info_bar (const gchar *primary_text,
376 const gchar *secondary_text,
377 gboolean edit_anyway)
378 {
379 GtkWidget *info_bar;
380 GtkWidget *hbox_content;
381 GtkWidget *image;
382 GtkWidget *vbox;
383 gchar *primary_markup;
384 gchar *secondary_markup;
385 GtkWidget *primary_label;
386 GtkWidget *secondary_label;
387
388 info_bar = gtk_info_bar_new ();
389
390 gtk_info_bar_add_button (GTK_INFO_BAR (info_bar), _("_Retry"), GTK_RESPONSE_OK);
391
392 if (edit_anyway)
393 {
394 gtk_info_bar_add_button (GTK_INFO_BAR (info_bar),
395 /* Translators: the access key chosen for this string should be
396 different from other main menu access keys (Open, Edit, View...) */
397 _("Edit Any_way"),
398 GTK_RESPONSE_YES);
399 gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar), GTK_MESSAGE_WARNING);
400 }
401 else
402 {
403 gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar), GTK_MESSAGE_ERROR);
404 }
405
406 gtk_info_bar_add_button (GTK_INFO_BAR (info_bar), _("_Cancel"), GTK_RESPONSE_CANCEL);
407
408 hbox_content = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
409
410 image = gtk_image_new_from_icon_name ("dialog-error-symbolic", GTK_ICON_SIZE_DIALOG);
411 gtk_box_pack_start (GTK_BOX (hbox_content), image, FALSE, FALSE, 0);
412 gtk_widget_set_halign (image, GTK_ALIGN_CENTER);
413 gtk_widget_set_valign (image, GTK_ALIGN_START);
414
415 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
416 gtk_box_pack_start (GTK_BOX (hbox_content), vbox, TRUE, TRUE, 0);
417
418 primary_markup = g_strdup_printf ("<b>%s</b>", primary_text);
419 primary_label = gtk_label_new (primary_markup);
420 g_free (primary_markup);
421 gtk_box_pack_start (GTK_BOX (vbox), primary_label, TRUE, TRUE, 0);
422 gtk_label_set_use_markup (GTK_LABEL (primary_label), TRUE);
423 gtk_label_set_line_wrap (GTK_LABEL (primary_label), TRUE);
424 gtk_widget_set_halign (primary_label, GTK_ALIGN_START);
425 gtk_widget_set_can_focus (primary_label, TRUE);
426 gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE);
427
428 if (secondary_text != NULL)
429 {
430 secondary_markup = g_strdup_printf ("<small>%s</small>", secondary_text);
431 secondary_label = gtk_label_new (secondary_markup);
432 g_free (secondary_markup);
433 gtk_box_pack_start (GTK_BOX (vbox), secondary_label, TRUE, TRUE, 0);
434 gtk_widget_set_can_focus (secondary_label, TRUE);
435 gtk_label_set_use_markup (GTK_LABEL (secondary_label), TRUE);
436 gtk_label_set_line_wrap (GTK_LABEL (secondary_label), TRUE);
437 gtk_label_set_selectable (GTK_LABEL (secondary_label), TRUE);
438 gtk_widget_set_halign (secondary_label, GTK_ALIGN_START);
439 }
440
441 create_combo_box (info_bar, vbox);
442 gtk_widget_show_all (hbox_content);
443 set_contents (info_bar, hbox_content);
444
445 return info_bar;
446 }
447
448 GtkWidget *
xed_io_loading_error_info_bar_new(GFile * location,const GtkSourceEncoding * encoding,const GError * error)449 xed_io_loading_error_info_bar_new (GFile *location,
450 const GtkSourceEncoding *encoding,
451 const GError *error)
452 {
453 gchar *error_message = NULL;
454 gchar *message_details = NULL;
455 gchar *full_formatted_uri;
456 gchar *uri_for_display;
457 gchar *temp_uri_for_display;
458 GtkWidget *info_bar;
459 gboolean edit_anyway = FALSE;
460 gboolean convert_error = FALSE;
461
462 g_return_val_if_fail (G_IS_FILE (location), NULL);
463 g_return_val_if_fail (error != NULL, NULL);
464 g_return_val_if_fail (error->domain == GTK_SOURCE_FILE_LOADER_ERROR ||
465 error->domain == G_IO_ERROR ||
466 error->domain == G_CONVERT_ERROR, NULL);
467
468 if (location != NULL)
469 {
470 full_formatted_uri = g_file_get_parse_name (location);
471 }
472 else
473 {
474 full_formatted_uri = g_strdup ("stdin");
475 }
476
477 /* Truncate the URI so it doesn't get insanely wide. Note that even
478 * though the dialog uses wrapped text, if the URI doesn't contain
479 * white space then the text-wrapping code is too stupid to wrap it.
480 */
481 temp_uri_for_display = xed_utils_str_middle_truncate (full_formatted_uri, MAX_URI_IN_DIALOG_LENGTH);
482 g_free (full_formatted_uri);
483
484 uri_for_display = g_markup_printf_escaped ("<i>%s</i>", temp_uri_for_display);
485 g_free (temp_uri_for_display);
486
487 if (is_gio_error (error, G_IO_ERROR_TOO_MANY_LINKS))
488 {
489 message_details = g_strdup (_("The number of followed links is limited and the actual file could not be found within this limit."));
490 }
491 else if (is_gio_error (error, G_IO_ERROR_PERMISSION_DENIED))
492 {
493 message_details = g_strdup (_("You do not have the permissions necessary to open the file."));
494 }
495 else if ((is_gio_error (error, G_IO_ERROR_INVALID_DATA) && encoding == NULL) ||
496 (error->domain == GTK_SOURCE_FILE_LOADER_ERROR &&
497 error->code == GTK_SOURCE_FILE_LOADER_ERROR_ENCODING_AUTO_DETECTION_FAILED))
498 {
499 message_details = g_strconcat (_("xed has not been able to detect "
500 "the character encoding."), "\n",
501 _("Please check that you are not trying to open a binary file."), "\n",
502 _("Select a character encoding from the menu and try again."), NULL);
503 convert_error = TRUE;
504 }
505 else if (error->domain == GTK_SOURCE_FILE_LOADER_ERROR &&
506 error->code == GTK_SOURCE_FILE_LOADER_ERROR_CONVERSION_FALLBACK)
507 {
508 error_message = g_strdup_printf (_("There was a problem opening the file %s."), uri_for_display);
509 message_details = g_strconcat (_("The file you opened has some invalid characters. "
510 "If you continue editing this file you could corrupt this "
511 "document."), "\n",
512 _("You can also choose another character encoding and try again."),
513 NULL);
514 edit_anyway = TRUE;
515 convert_error = TRUE;
516 }
517 else if (is_gio_error (error, G_IO_ERROR_INVALID_DATA) && encoding != NULL)
518 {
519 gchar *encoding_name = gtk_source_encoding_to_string (encoding);
520
521 error_message = g_strdup_printf (_("Could not open the file %s using the %s character encoding."),
522 uri_for_display,
523 encoding_name);
524 message_details = g_strconcat (_("Please check that you are not trying to open a binary file."), "\n",
525 _("Select a different character encoding from the menu and try again."), NULL);
526 convert_error = TRUE;
527
528 g_free (encoding_name);
529 }
530 else
531 {
532 parse_error (error, &error_message, &message_details, location, uri_for_display);
533 }
534
535 if (error_message == NULL)
536 {
537 error_message = g_strdup_printf (_("Could not open the file %s."), uri_for_display);
538 }
539
540 if (convert_error)
541 {
542 info_bar = create_conversion_error_info_bar (error_message, message_details, edit_anyway);
543 }
544 else
545 {
546 info_bar = create_io_loading_error_info_bar (error_message, message_details, is_recoverable_error (error));
547 }
548
549 g_free (uri_for_display);
550 g_free (error_message);
551 g_free (message_details);
552
553 return info_bar;
554 }
555
556 GtkWidget *
xed_conversion_error_while_saving_info_bar_new(GFile * location,const GtkSourceEncoding * encoding,const GError * error)557 xed_conversion_error_while_saving_info_bar_new (GFile *location,
558 const GtkSourceEncoding *encoding,
559 const GError *error)
560 {
561 gchar *error_message = NULL;
562 gchar *message_details = NULL;
563 gchar *full_formatted_uri;
564 gchar *encoding_name;
565 gchar *uri_for_display;
566 gchar *temp_uri_for_display;
567 GtkWidget *info_bar;
568
569 g_return_val_if_fail (G_IS_FILE (location), NULL);
570 g_return_val_if_fail (error != NULL, NULL);
571 g_return_val_if_fail (error->domain == G_CONVERT_ERROR ||
572 error->domain == G_IO_ERROR, NULL);
573 g_return_val_if_fail (encoding != NULL, NULL);
574
575 full_formatted_uri = g_file_get_parse_name (location);
576
577 /* Truncate the URI so it doesn't get insanely wide. Note that even
578 * though the dialog uses wrapped text, if the URI doesn't contain
579 * white space then the text-wrapping code is too stupid to wrap it.
580 */
581 temp_uri_for_display = xed_utils_str_middle_truncate (full_formatted_uri, MAX_URI_IN_DIALOG_LENGTH);
582 g_free (full_formatted_uri);
583
584 uri_for_display = g_markup_printf_escaped ("<i>%s</i>", temp_uri_for_display);
585 g_free (temp_uri_for_display);
586
587 encoding_name = gtk_source_encoding_to_string (encoding);
588
589 error_message = g_strdup_printf (_("Could not save the file %s using the %s character encoding."),
590 uri_for_display,
591 encoding_name);
592 message_details = g_strconcat (_("The document contains one or more characters that cannot be encoded "
593 "using the specified character encoding."), "\n",
594 _("Select a different character encoding from the menu and try again."), NULL);
595
596 info_bar = create_conversion_error_info_bar (error_message, message_details, FALSE);
597
598 g_free (uri_for_display);
599 g_free (encoding_name);
600 g_free (error_message);
601 g_free (message_details);
602
603 return info_bar;
604 }
605
606 const GtkSourceEncoding *
xed_conversion_error_info_bar_get_encoding(GtkWidget * info_bar)607 xed_conversion_error_info_bar_get_encoding (GtkWidget *info_bar)
608 {
609 gpointer menu;
610
611 g_return_val_if_fail (GTK_IS_INFO_BAR (info_bar), NULL);
612
613 menu = g_object_get_data (G_OBJECT (info_bar), "xed-info-bar-encoding-menu");
614 g_return_val_if_fail (menu, NULL);
615
616 return xed_encodings_combo_box_get_selected_encoding (XED_ENCODINGS_COMBO_BOX (menu));
617 }
618
619 GtkWidget *
xed_file_already_open_warning_info_bar_new(GFile * location)620 xed_file_already_open_warning_info_bar_new (GFile *location)
621 {
622 GtkWidget *info_bar;
623 GtkWidget *hbox_content;
624 GtkWidget *image;
625 GtkWidget *vbox;
626 gchar *primary_markup;
627 gchar *secondary_markup;
628 GtkWidget *primary_label;
629 GtkWidget *secondary_label;
630 gchar *primary_text;
631 const gchar *secondary_text;
632 gchar *full_formatted_uri;
633 gchar *uri_for_display;
634 gchar *temp_uri_for_display;
635
636 g_return_val_if_fail (G_IS_FILE (location), NULL);
637
638 full_formatted_uri = g_file_get_parse_name (location);
639
640 /* Truncate the URI so it doesn't get insanely wide. Note that even
641 * though the dialog uses wrapped text, if the URI doesn't contain
642 * white space then the text-wrapping code is too stupid to wrap it.
643 */
644 temp_uri_for_display = xed_utils_str_middle_truncate (full_formatted_uri, MAX_URI_IN_DIALOG_LENGTH);
645 g_free (full_formatted_uri);
646
647 uri_for_display = g_markup_printf_escaped ("<i>%s</i>", temp_uri_for_display);
648 g_free (temp_uri_for_display);
649
650 info_bar = gtk_info_bar_new ();
651 gtk_info_bar_add_button (GTK_INFO_BAR (info_bar),
652 /* Translators: the access key chosen for this string should be
653 different from other main menu access keys (Open, Edit, View...) */
654 _("Edit Any_way"),
655 GTK_RESPONSE_YES);
656 gtk_info_bar_add_button (GTK_INFO_BAR (info_bar),
657 /* Translators: the access key chosen for this string should be
658 different from other main menu access keys (Open, Edit, View...) */
659 _("D_on't Edit"),
660 GTK_RESPONSE_CANCEL);
661 gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar), GTK_MESSAGE_WARNING);
662
663 hbox_content = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
664
665 image = gtk_image_new_from_icon_name ("dialog-warning-symbolic", GTK_ICON_SIZE_DIALOG);
666 gtk_box_pack_start (GTK_BOX (hbox_content), image, FALSE, FALSE, 0);
667 gtk_widget_set_halign (image, GTK_ALIGN_CENTER);
668 gtk_widget_set_valign (image, GTK_ALIGN_START);
669
670 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
671 gtk_box_pack_start (GTK_BOX (hbox_content), vbox, TRUE, TRUE, 0);
672
673 primary_text = g_strdup_printf (_("This file (%s) is already open in another xed window."), uri_for_display);
674 g_free (uri_for_display);
675
676 primary_markup = g_strdup_printf ("<b>%s</b>", primary_text);
677 g_free (primary_text);
678 primary_label = gtk_label_new (primary_markup);
679 g_free (primary_markup);
680 gtk_box_pack_start (GTK_BOX (vbox), primary_label, TRUE, TRUE, 0);
681 gtk_label_set_use_markup (GTK_LABEL (primary_label), TRUE);
682 gtk_label_set_line_wrap (GTK_LABEL (primary_label), TRUE);
683 gtk_widget_set_halign (primary_label, GTK_ALIGN_START);
684 gtk_widget_set_can_focus (primary_label, TRUE);
685 gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE);
686
687 secondary_text = _("xed opened this instance of the file in a non-editable way. "
688 "Do you want to edit it anyway?");
689 secondary_markup = g_strdup_printf ("<small>%s</small>", secondary_text);
690 secondary_label = gtk_label_new (secondary_markup);
691 g_free (secondary_markup);
692 gtk_box_pack_start (GTK_BOX (vbox), secondary_label, TRUE, TRUE, 0);
693 gtk_widget_set_can_focus (secondary_label, TRUE);
694 gtk_label_set_use_markup (GTK_LABEL (secondary_label), TRUE);
695 gtk_label_set_line_wrap (GTK_LABEL (secondary_label), TRUE);
696 gtk_label_set_selectable (GTK_LABEL (secondary_label), TRUE);
697 gtk_widget_set_halign (secondary_label, GTK_ALIGN_START);
698
699 gtk_widget_show_all (hbox_content);
700 set_contents (info_bar, hbox_content);
701
702 return info_bar;
703 }
704
705 GtkWidget *
xed_externally_modified_saving_error_info_bar_new(GFile * location,const GError * error)706 xed_externally_modified_saving_error_info_bar_new (GFile *location,
707 const GError *error)
708 {
709 GtkWidget *info_bar;
710 GtkWidget *hbox_content;
711 GtkWidget *image;
712 GtkWidget *vbox;
713 gchar *primary_markup;
714 gchar *secondary_markup;
715 GtkWidget *primary_label;
716 GtkWidget *secondary_label;
717 gchar *primary_text;
718 const gchar *secondary_text;
719 gchar *full_formatted_uri;
720 gchar *uri_for_display;
721 gchar *temp_uri_for_display;
722
723 g_return_val_if_fail (G_IS_FILE (location), NULL);
724 g_return_val_if_fail (error != NULL, NULL);
725 g_return_val_if_fail (error->domain == GTK_SOURCE_FILE_SAVER_ERROR, NULL);
726 g_return_val_if_fail (error->code == GTK_SOURCE_FILE_SAVER_ERROR_EXTERNALLY_MODIFIED, NULL);
727
728 full_formatted_uri = g_file_get_parse_name (location);
729
730 /* Truncate the URI so it doesn't get insanely wide. Note that even
731 * though the dialog uses wrapped text, if the URI doesn't contain
732 * white space then the text-wrapping code is too stupid to wrap it.
733 */
734 temp_uri_for_display = xed_utils_str_middle_truncate (full_formatted_uri, MAX_URI_IN_DIALOG_LENGTH);
735 g_free (full_formatted_uri);
736
737 uri_for_display = g_markup_printf_escaped ("<i>%s</i>", temp_uri_for_display);
738 g_free (temp_uri_for_display);
739
740 info_bar = gtk_info_bar_new ();
741
742 gtk_info_bar_add_button (GTK_INFO_BAR (info_bar), _("S_ave Anyway"), GTK_RESPONSE_YES);
743 gtk_info_bar_add_button (GTK_INFO_BAR (info_bar), _("D_on't Save"), GTK_RESPONSE_CANCEL);
744 gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar), GTK_MESSAGE_WARNING);
745
746 hbox_content = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
747
748 image = gtk_image_new_from_icon_name ("dialog-warning-symbolic", GTK_ICON_SIZE_DIALOG);
749 gtk_box_pack_start (GTK_BOX (hbox_content), image, FALSE, FALSE, 0);
750 gtk_widget_set_halign (image, GTK_ALIGN_CENTER);
751 gtk_widget_set_valign (image, GTK_ALIGN_START);
752
753 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
754 gtk_box_pack_start (GTK_BOX (hbox_content), vbox, TRUE, TRUE, 0);
755
756 /* FIXME: review this message, it's not clear since for the user the "modification"
757 * could be interpreted as the changes he made in the document. beside "reading" is
758 * not accurate (since last load/save)
759 */
760 primary_text = g_strdup_printf (_("The file %s has been modified since reading it."), uri_for_display);
761 g_free (uri_for_display);
762
763 primary_markup = g_strdup_printf ("<b>%s</b>", primary_text);
764 g_free (primary_text);
765 primary_label = gtk_label_new (primary_markup);
766 g_free (primary_markup);
767 gtk_box_pack_start (GTK_BOX (vbox), primary_label, TRUE, TRUE, 0);
768 gtk_label_set_use_markup (GTK_LABEL (primary_label), TRUE);
769 gtk_label_set_line_wrap (GTK_LABEL (primary_label), TRUE);
770 gtk_widget_set_halign (primary_label, GTK_ALIGN_START);
771 gtk_widget_set_can_focus (primary_label, TRUE);
772 gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE);
773
774 secondary_text = _("If you save it, all the external changes could be lost. Save it anyway?");
775 secondary_markup = g_strdup_printf ("<small>%s</small>", secondary_text);
776 secondary_label = gtk_label_new (secondary_markup);
777 g_free (secondary_markup);
778 gtk_box_pack_start (GTK_BOX (vbox), secondary_label, TRUE, TRUE, 0);
779 gtk_widget_set_can_focus (secondary_label, TRUE);
780 gtk_label_set_use_markup (GTK_LABEL (secondary_label), TRUE);
781 gtk_label_set_line_wrap (GTK_LABEL (secondary_label), TRUE);
782 gtk_label_set_selectable (GTK_LABEL (secondary_label), TRUE);
783 gtk_widget_set_halign (secondary_label, GTK_ALIGN_START);
784
785 gtk_widget_show_all (hbox_content);
786 set_contents (info_bar, hbox_content);
787
788 return info_bar;
789 }
790
791 GtkWidget *
xed_no_backup_saving_error_info_bar_new(GFile * location,const GError * error)792 xed_no_backup_saving_error_info_bar_new (GFile *location,
793 const GError *error)
794 {
795 GtkWidget *info_bar;
796 GtkWidget *hbox_content;
797 GtkWidget *image;
798 GtkWidget *vbox;
799 gchar *primary_markup;
800 gchar *secondary_markup;
801 GtkWidget *primary_label;
802 GtkWidget *secondary_label;
803 gchar *primary_text;
804 const gchar *secondary_text;
805 gchar *full_formatted_uri;
806 gchar *uri_for_display;
807 gchar *temp_uri_for_display;
808 gboolean create_backup_copy;
809 GSettings *editor_settings;
810
811 g_return_val_if_fail (G_IS_FILE (location), NULL);
812 g_return_val_if_fail (error != NULL, NULL);
813 g_return_val_if_fail (error->domain == G_IO_ERROR &&
814 error->code == G_IO_ERROR_CANT_CREATE_BACKUP, NULL);
815
816 full_formatted_uri = g_file_get_parse_name (location);
817
818 /* Truncate the URI so it doesn't get insanely wide. Note that even
819 * though the dialog uses wrapped text, if the URI doesn't contain
820 * white space then the text-wrapping code is too stupid to wrap it.
821 */
822 temp_uri_for_display = xed_utils_str_middle_truncate (full_formatted_uri, MAX_URI_IN_DIALOG_LENGTH);
823 g_free (full_formatted_uri);
824
825 uri_for_display = g_markup_printf_escaped ("<i>%s</i>", temp_uri_for_display);
826 g_free (temp_uri_for_display);
827
828 info_bar = gtk_info_bar_new ();
829
830 gtk_info_bar_add_button (GTK_INFO_BAR (info_bar), _("S_ave Anyway"), GTK_RESPONSE_YES);
831 gtk_info_bar_add_button (GTK_INFO_BAR (info_bar), _("D_on't Save"), GTK_RESPONSE_CANCEL);
832 gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar), GTK_MESSAGE_WARNING);
833
834 hbox_content = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
835
836 image = gtk_image_new_from_icon_name ("dialog-warning-symbolic", GTK_ICON_SIZE_DIALOG);
837 gtk_box_pack_start (GTK_BOX (hbox_content), image, FALSE, FALSE, 0);
838 gtk_widget_set_halign (image, GTK_ALIGN_CENTER);
839 gtk_widget_set_valign (image, GTK_ALIGN_START);
840
841 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
842 gtk_box_pack_start (GTK_BOX (hbox_content), vbox, TRUE, TRUE, 0);
843
844 editor_settings = g_settings_new ("org.x.editor.preferences.editor");
845 create_backup_copy = g_settings_get_boolean (editor_settings, XED_SETTINGS_CREATE_BACKUP_COPY);
846 g_object_unref (editor_settings);
847
848 // FIXME: review this messages
849 if (create_backup_copy)
850 {
851 primary_text = g_strdup_printf (_("Could not create a backup file while saving %s"), uri_for_display);
852 }
853 else
854 {
855 primary_text = g_strdup_printf (_("Could not create a temporary backup file while saving %s"), uri_for_display);
856 }
857
858 g_free (uri_for_display);
859
860 primary_markup = g_strdup_printf ("<b>%s</b>", primary_text);
861 g_free (primary_text);
862 primary_label = gtk_label_new (primary_markup);
863 g_free (primary_markup);
864 gtk_box_pack_start (GTK_BOX (vbox), primary_label, TRUE, TRUE, 0);
865 gtk_label_set_use_markup (GTK_LABEL (primary_label), TRUE);
866 gtk_label_set_line_wrap (GTK_LABEL (primary_label), TRUE);
867 gtk_widget_set_halign (primary_label, GTK_ALIGN_START);
868 gtk_widget_set_can_focus (primary_label, TRUE);
869 gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE);
870
871 secondary_text = _("xed could not back up the old copy of the file before saving the new one. "
872 "You can ignore this warning and save the file anyway, but if an error "
873 "occurs while saving, you could lose the old copy of the file. Save anyway?");
874 secondary_markup = g_strdup_printf ("<small>%s</small>", secondary_text);
875 secondary_label = gtk_label_new (secondary_markup);
876 g_free (secondary_markup);
877 gtk_box_pack_start (GTK_BOX (vbox), secondary_label, TRUE, TRUE, 0);
878 gtk_widget_set_can_focus (secondary_label, TRUE);
879 gtk_label_set_use_markup (GTK_LABEL (secondary_label), TRUE);
880 gtk_label_set_line_wrap (GTK_LABEL (secondary_label), TRUE);
881 gtk_label_set_selectable (GTK_LABEL (secondary_label), TRUE);
882 gtk_widget_set_halign (secondary_label, GTK_ALIGN_START);
883
884 gtk_widget_show_all (hbox_content);
885 set_contents (info_bar, hbox_content);
886
887 return info_bar;
888 }
889
890 GtkWidget *
xed_unrecoverable_saving_error_info_bar_new(GFile * location,const GError * error)891 xed_unrecoverable_saving_error_info_bar_new (GFile *location,
892 const GError *error)
893 {
894 gchar *error_message = NULL;
895 gchar *message_details = NULL;
896 gchar *full_formatted_uri;
897 gchar *scheme_string;
898 gchar *scheme_markup;
899 gchar *uri_for_display;
900 gchar *temp_uri_for_display;
901 GtkWidget *info_bar;
902
903 g_return_val_if_fail (G_IS_FILE (location), NULL);
904 g_return_val_if_fail (error != NULL, NULL);
905 g_return_val_if_fail (error->domain == GTK_SOURCE_FILE_SAVER_ERROR || error->domain == G_IO_ERROR, NULL);
906
907 full_formatted_uri = g_file_get_parse_name (location);
908
909 /* Truncate the URI so it doesn't get insanely wide. Note that even
910 * though the dialog uses wrapped text, if the URI doesn't contain
911 * white space then the text-wrapping code is too stupid to wrap it.
912 */
913 temp_uri_for_display = xed_utils_str_middle_truncate (full_formatted_uri, MAX_URI_IN_DIALOG_LENGTH);
914 g_free (full_formatted_uri);
915
916 uri_for_display = g_markup_printf_escaped ("<i>%s</i>", temp_uri_for_display);
917 g_free (temp_uri_for_display);
918
919 if (is_gio_error (error, G_IO_ERROR_NOT_SUPPORTED))
920 {
921 scheme_string = g_file_get_uri_scheme (location);
922
923 if ((scheme_string != NULL) && g_utf8_validate (scheme_string, -1, NULL))
924 {
925 scheme_markup = g_markup_printf_escaped ("<i>%s:</i>", scheme_string);
926
927 /* Translators: %s is a URI scheme (like for example http:, ftp:, etc.) */
928 message_details = g_strdup_printf (_("xed cannot handle %s locations in write mode. "
929 "Please check that you typed the "
930 "location correctly and try again."),
931 scheme_markup);
932 g_free (scheme_markup);
933 }
934 else
935 {
936 message_details = g_strdup (_("xed cannot handle this location in write mode. "
937 "Please check that you typed the "
938 "location correctly and try again."));
939 }
940
941 g_free (scheme_string);
942 }
943 else if (is_gio_error (error, G_IO_ERROR_INVALID_FILENAME))
944 {
945 message_details = g_strdup (_("%s is not a valid location. "
946 "Please check that you typed the "
947 "location correctly and try again."));
948 }
949 else if (is_gio_error (error, G_IO_ERROR_PERMISSION_DENIED))
950 {
951 message_details = g_strdup (_("You do not have the permissions necessary to save the file. "
952 "Please check that you typed the "
953 "location correctly and try again."));
954 }
955 else if (is_gio_error (error, G_IO_ERROR_NO_SPACE))
956 {
957 message_details = g_strdup (_("There is not enough disk space to save the file. "
958 "Please free some disk space and try again."));
959 }
960 else if (is_gio_error (error, G_IO_ERROR_READ_ONLY))
961 {
962 message_details = g_strdup (_("You are trying to save the file on a read-only disk. "
963 "Please check that you typed the location "
964 "correctly and try again."));
965 }
966 else if (is_gio_error (error, G_IO_ERROR_EXISTS))
967 {
968 message_details = g_strdup (_("A file with the same name already exists. "
969 "Please use a different name."));
970 }
971 else if (is_gio_error (error, G_IO_ERROR_FILENAME_TOO_LONG))
972 {
973 message_details = g_strdup (_("The disk where you are trying to save the file has "
974 "a limitation on length of the file names. "
975 "Please use a shorter name."));
976 }
977 #if 0
978 /* FIXME this error can not occur for a file saving. Either remove the
979 * code here, or improve the GtkSourceFileSaver so this error can occur.
980 */
981 else if (error->domain == XED_DOCUMENT_ERROR && error->code == XED_DOCUMENT_ERROR_TOO_BIG)
982 {
983 message_details = g_strdup (_("The disk where you are trying to save the file has "
984 "a limitation on file sizes. Please try saving "
985 "a smaller file or saving it to a disk that does not "
986 "have this limitation."));
987 }
988 #endif
989 else
990 {
991 parse_error (error, &error_message, &message_details, location, uri_for_display);
992 }
993
994 if (error_message == NULL)
995 {
996 error_message = g_strdup_printf (_("Could not save the file %s."), uri_for_display);
997 }
998
999 info_bar = create_io_loading_error_info_bar (error_message, message_details, FALSE);
1000
1001 g_free (uri_for_display);
1002 g_free (error_message);
1003 g_free (message_details);
1004
1005 return info_bar;
1006 }
1007
1008 GtkWidget *
xed_externally_modified_info_bar_new(GFile * location,gboolean document_modified)1009 xed_externally_modified_info_bar_new (GFile *location,
1010 gboolean document_modified)
1011 {
1012 gchar *full_formatted_uri;
1013 gchar *uri_for_display;
1014 gchar *temp_uri_for_display;
1015 const gchar *primary_text;
1016 const gchar *secondary_text;
1017 GtkWidget *info_bar;
1018
1019 g_return_val_if_fail (G_IS_FILE (location), NULL);
1020
1021 full_formatted_uri = g_file_get_parse_name (location);
1022
1023 /* Truncate the URI so it doesn't get insanely wide. Note that even
1024 * though the dialog uses wrapped text, if the URI doesn't contain
1025 * white space then the text-wrapping code is too stupid to wrap it.
1026 */
1027 temp_uri_for_display = xed_utils_str_middle_truncate (full_formatted_uri, MAX_URI_IN_DIALOG_LENGTH);
1028 g_free (full_formatted_uri);
1029
1030 uri_for_display = g_markup_printf_escaped ("<i>%s</i>", temp_uri_for_display);
1031 g_free (temp_uri_for_display);
1032
1033 // FIXME: review this message, it's not clear since for the user the "modification"
1034 // could be interpreted as the changes he made in the document. beside "reading" is
1035 // not accurate (since last load/save)
1036 primary_text = g_strdup_printf (_("The file %s changed on disk."), uri_for_display);
1037 g_free (uri_for_display);
1038
1039 if (document_modified)
1040 {
1041 secondary_text = _("Do you want to drop your changes and reload the file?");
1042 }
1043 else
1044 {
1045 secondary_text = _("Do you want to reload the file?");
1046 }
1047
1048 info_bar = gtk_info_bar_new ();
1049
1050 gtk_info_bar_add_button (GTK_INFO_BAR (info_bar), _("_Reload"), GTK_RESPONSE_OK);
1051 gtk_info_bar_add_button (GTK_INFO_BAR (info_bar), _("_Cancel"), GTK_RESPONSE_CANCEL);
1052 gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar), GTK_MESSAGE_WARNING);
1053
1054 set_info_bar_text_and_icon (info_bar, "dialog-warning-symbolic", primary_text, secondary_text);
1055
1056 return info_bar;
1057 }
1058
1059 GtkWidget *
xed_invalid_character_info_bar_new(GFile * location)1060 xed_invalid_character_info_bar_new (GFile *location)
1061 {
1062 GtkWidget *info_bar;
1063 GtkWidget *hbox_content;
1064 GtkWidget *image;
1065 GtkWidget *vbox;
1066 GtkWidget *primary_label;
1067 GtkWidget *secondary_label;
1068 gchar *primary_markup;
1069 gchar *secondary_markup;
1070 gchar *primary_text;
1071 gchar *full_formatted_uri;
1072 gchar *uri_for_display;
1073 gchar *temp_uri_for_display;
1074 const gchar *secondary_text;
1075
1076 g_return_val_if_fail (G_IS_FILE (location), NULL);
1077
1078 full_formatted_uri = g_file_get_parse_name (location);
1079
1080 /* Truncate the URI so it doesn't get insanely wide. Note that even
1081 * though the dialog uses wrapped text, if the URI doesn't contain
1082 * white space then the text-wrapping code is too stupid to wrap it.
1083 */
1084 temp_uri_for_display = xed_utils_str_middle_truncate (full_formatted_uri, MAX_URI_IN_DIALOG_LENGTH);
1085 g_free (full_formatted_uri);
1086
1087 uri_for_display = g_markup_printf_escaped ("<i>%s</i>", temp_uri_for_display);
1088 g_free (temp_uri_for_display);
1089
1090 info_bar = gtk_info_bar_new ();
1091
1092 gtk_info_bar_add_button (GTK_INFO_BAR (info_bar), _("S_ave Anyway"), GTK_RESPONSE_YES);
1093 gtk_info_bar_add_button (GTK_INFO_BAR (info_bar),
1094 _("D_on't Save"),
1095 GTK_RESPONSE_CANCEL);
1096 gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar), GTK_MESSAGE_WARNING);
1097
1098 hbox_content = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
1099
1100 image = gtk_image_new_from_icon_name ("dialog-warning-symbolic", GTK_ICON_SIZE_DIALOG);
1101 gtk_box_pack_start (GTK_BOX (hbox_content), image, FALSE, FALSE, 0);
1102 gtk_widget_set_valign (image, GTK_ALIGN_START);
1103
1104 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
1105 gtk_box_pack_start (GTK_BOX (hbox_content), vbox, TRUE, TRUE, 0);
1106
1107 primary_text = g_strdup_printf (_("Some invalid chars have been detected while saving %s"), uri_for_display);
1108
1109 g_free (uri_for_display);
1110
1111 primary_markup = g_strdup_printf ("<b>%s</b>", primary_text);
1112 g_free (primary_text);
1113 primary_label = gtk_label_new (primary_markup);
1114 g_free (primary_markup);
1115 gtk_box_pack_start (GTK_BOX (vbox), primary_label, TRUE, TRUE, 0);
1116 gtk_label_set_use_markup (GTK_LABEL (primary_label), TRUE);
1117 gtk_label_set_line_wrap (GTK_LABEL (primary_label), TRUE);
1118 gtk_widget_set_halign (primary_label, GTK_ALIGN_START);
1119 gtk_widget_set_can_focus (primary_label, TRUE);
1120 gtk_label_set_selectable (GTK_LABEL (primary_label), TRUE);
1121
1122 secondary_text = _("If you continue saving this file you can corrupt the document. "
1123 " Save anyway?");
1124 secondary_markup = g_strdup_printf ("<small>%s</small>", secondary_text);
1125 secondary_label = gtk_label_new (secondary_markup);
1126 g_free (secondary_markup);
1127 gtk_box_pack_start (GTK_BOX (vbox), secondary_label, TRUE, TRUE, 0);
1128 gtk_widget_set_can_focus (secondary_label, TRUE);
1129 gtk_label_set_use_markup (GTK_LABEL (secondary_label), TRUE);
1130 gtk_label_set_line_wrap (GTK_LABEL (secondary_label), TRUE);
1131 gtk_label_set_selectable (GTK_LABEL (secondary_label), TRUE);
1132 gtk_widget_set_halign (secondary_label, GTK_ALIGN_START);
1133
1134 gtk_widget_show_all (hbox_content);
1135 set_contents (info_bar, hbox_content);
1136
1137 return info_bar;
1138 }
1139