]> git.sur5r.net Git - glabels/blob - glabels2/src/file.c
- View now tracks label resize events.
[glabels] / glabels2 / src / file.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  file.c:  FILE menu dialog module
5  *
6  *  Copyright (C) 2001  Jim Evins <evins@snaught.com>.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program 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
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21  */
22
23 #include <config.h>
24
25 #include <gnome.h>
26 #include <string.h>
27
28 #include "xml-label.h"
29 #include "file.h"
30 #include "recent.h"
31 #include "hig.h"
32 #include "util.h"
33 #include "wdgt-media-select.h"
34 #include "wdgt-rotate-label.h"
35 #include "debug.h"
36
37 /*===========================================*/
38 /* Private globals                           */
39 /*===========================================*/
40
41 /* Saved state for new dialog */
42 static gchar   *page_size   = NULL;
43 static gchar   *sheet_name  = NULL;
44 static gboolean rotate_flag = FALSE;
45
46 /* Saved state of file selectors */
47 static gchar *open_path = NULL;
48 static gchar *save_path = NULL;
49
50 /*===========================================*/
51 /* Local function prototypes.                */
52 /*===========================================*/
53 static void create_new_dialog_widgets        (glHigDialog       *dlg);
54 static void new_template_changed             (glWdgtMediaSelect *select,
55                                               gpointer           data);
56 static void new_response                     (GtkDialog         *dlg,
57                                               gint               response,
58                                               gpointer           user_data);
59
60 static void create_properties_dialog_widgets (glHigDialog       *dlg,
61                                               glLabel           *label);
62 static void properties_template_changed      (glWdgtMediaSelect *select,
63                                               gpointer           data);
64 static void properties_response              (GtkDialog         *dlg,
65                                               gint               response,
66                                               gpointer           user_data);
67
68 static void open_ok                          (GtkWidget         *widget,
69                                               GtkFileSelection  *fsel);
70
71 static void save_as_ok_cb                    (GtkWidget         *widget,
72                                               GtkFileSelection  *fsel);
73 static void save_as_cancel_cb                (GtkWidget         *widget,
74                                               GtkFileSelection  *fsel);
75 static void save_as_destroy_cb               (GtkWidget         *widget,
76                                               gboolean          *destroy_flag);
77
78 \f
79 /*****************************************************************************/
80 /* "New" menu callback.                                                      */
81 /*****************************************************************************/
82 void
83 gl_file_new (GtkWindow *window)
84 {
85         GtkWidget    *dlg;
86
87         gl_debug (DEBUG_FILE, "START");
88
89         g_return_if_fail (window != NULL);
90
91         dlg = gl_hig_dialog_new_with_buttons (_("New Label or Card"),
92                                               window,
93                                               GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
94                                               GTK_STOCK_OK, GTK_RESPONSE_OK,
95                                               GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
96                                               NULL);
97
98         create_new_dialog_widgets (GL_HIG_DIALOG (dlg));
99
100         g_object_set_data (G_OBJECT (dlg), "parent_window", window);
101
102         g_signal_connect (G_OBJECT(dlg), "response",
103                           G_CALLBACK (new_response), dlg);
104
105         gtk_window_set_resizable (GTK_WINDOW (dlg), FALSE);
106         gtk_widget_show_all (GTK_WIDGET (dlg));
107
108         gl_debug (DEBUG_FILE, "END");
109 }
110
111 /*---------------------------------------------------------------------------*/
112 /* PRIVATE.  Create widgets.                                                 */
113 /*---------------------------------------------------------------------------*/
114 static void
115 create_new_dialog_widgets (glHigDialog *dlg)
116 {
117         GtkWidget *wframe, *template_entry, *rotate_sel;
118
119         gl_debug (DEBUG_FILE, "START");
120
121         wframe = gl_hig_category_new (_("Media Type"));
122         gl_hig_dialog_add_widget (dlg, wframe);
123
124         template_entry = gl_wdgt_media_select_new ();
125         gl_hig_category_add_widget (GL_HIG_CATEGORY(wframe), template_entry);
126
127         wframe = gl_hig_category_new (_("Label orientation"));
128         gl_hig_dialog_add_widget (dlg, wframe);
129
130         rotate_sel = gl_wdgt_rotate_label_new ();
131         gl_hig_category_add_widget (GL_HIG_CATEGORY(wframe), rotate_sel);
132
133         g_object_set_data (G_OBJECT (dlg), "template_entry", template_entry);
134         g_object_set_data (G_OBJECT (dlg), "rotate_sel", rotate_sel);
135
136         g_signal_connect (G_OBJECT (template_entry), "changed",
137                           G_CALLBACK (new_template_changed), rotate_sel);
138
139         if (page_size != NULL) {
140                 gl_wdgt_media_select_set_page_size (GL_WDGT_MEDIA_SELECT (template_entry),
141                                                page_size);
142         }
143         if (sheet_name != NULL) {
144                 gl_wdgt_media_select_set_name (GL_WDGT_MEDIA_SELECT (template_entry),
145                                           sheet_name);
146                 gl_wdgt_rotate_label_set_template_name (GL_WDGT_ROTATE_LABEL
147                                                     (rotate_sel), sheet_name);
148         } else {
149                 sheet_name =
150                     gl_wdgt_media_select_get_name (GL_WDGT_MEDIA_SELECT (template_entry));
151                 gl_wdgt_rotate_label_set_template_name (GL_WDGT_ROTATE_LABEL
152                                                     (rotate_sel), sheet_name);
153         }
154         gl_wdgt_rotate_label_set_state (GL_WDGT_ROTATE_LABEL (rotate_sel), rotate_flag);
155
156         gl_debug (DEBUG_FILE, "END");
157 }
158
159 /*---------------------------------------------------------------------------*/
160 /* PRIVATE.  New template changed callback.                                  */
161 /*---------------------------------------------------------------------------*/
162 static void
163 new_template_changed (glWdgtMediaSelect *select,
164                       gpointer           data)
165 {
166         glWdgtRotateLabel *rotate_sel = GL_WDGT_ROTATE_LABEL (data);
167         gchar             *name;
168
169         gl_debug (DEBUG_FILE, "START");
170
171         name = gl_wdgt_media_select_get_name (GL_WDGT_MEDIA_SELECT (select));
172
173         gl_wdgt_rotate_label_set_template_name (GL_WDGT_ROTATE_LABEL (rotate_sel),
174                                                 name);
175
176         g_free (name);
177
178         gl_debug (DEBUG_FILE, "END");
179 }
180
181 /*---------------------------------------------------------------------------*/
182 /* PRIVATE.  New "ok" button callback.                                       */
183 /*---------------------------------------------------------------------------*/
184 static void
185 new_response (GtkDialog *dlg,
186               gint       response,
187               gpointer   user_data)
188 {
189         GtkWidget  *template_entry, *rotate_sel, *new_window;
190         glTemplate *template;
191         glLabel    *label;
192         gint        ret;
193         glWindow   *window;
194
195         gl_debug (DEBUG_FILE, "START");
196
197         switch (response) {
198         case GTK_RESPONSE_OK:
199                 template_entry =
200                         GTK_WIDGET (g_object_get_data (G_OBJECT (dlg),
201                                                        "template_entry"));
202                 rotate_sel = GTK_WIDGET (g_object_get_data (G_OBJECT (dlg),
203                                                             "rotate_sel"));
204
205                 if (page_size != NULL)
206                         g_free (page_size);
207                 page_size =
208                         gl_wdgt_media_select_get_page_size (GL_WDGT_MEDIA_SELECT (template_entry));
209
210                 if (sheet_name != NULL)
211                         g_free (sheet_name);
212                 sheet_name =
213                         gl_wdgt_media_select_get_name (GL_WDGT_MEDIA_SELECT (template_entry));
214
215                 rotate_flag =
216                         gl_wdgt_rotate_label_get_state (GL_WDGT_ROTATE_LABEL (rotate_sel));
217
218                 template = gl_template_from_name (sheet_name);
219
220                 label = GL_LABEL(gl_label_new ());
221                 gl_label_set_template (label, template);
222                 gl_label_set_rotate_flag (label, rotate_flag);
223
224                 window =
225                         GL_WINDOW (g_object_get_data (G_OBJECT (dlg),
226                                                       "parent_window"));
227                 if ( gl_window_is_empty (window) ) {
228                         gl_window_set_label (window, label);
229                 } else {
230                         new_window = gl_window_new_from_label (label);
231                         gtk_widget_show_all (new_window);
232                 }
233                 
234
235                 break;
236         }
237
238         gtk_widget_destroy (GTK_WIDGET (dlg));
239
240         gl_debug (DEBUG_FILE, "END");
241 }
242
243 \f
244 /*****************************************************************************/
245 /* "Properties" menu callback.                                               */
246 /*****************************************************************************/
247 void
248 gl_file_properties (glLabel   *label,
249                     GtkWindow *window)
250 {
251         GtkWidget    *dlg;
252
253         gl_debug (DEBUG_FILE, "START");
254
255         g_return_if_fail (label && GL_IS_LABEL (label));
256         g_return_if_fail (window && GTK_IS_WINDOW (window));
257
258         dlg = gl_hig_dialog_new_with_buttons (_("Label properties"),
259                                               window,
260                                               GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
261                                               GTK_STOCK_OK, GTK_RESPONSE_OK,
262                                               GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
263                                               NULL);
264
265         create_properties_dialog_widgets (GL_HIG_DIALOG (dlg), label);
266
267         g_object_set_data (G_OBJECT (dlg), "label", label);
268
269         g_signal_connect (G_OBJECT(dlg), "response",
270                           G_CALLBACK (properties_response), dlg);
271
272         gtk_window_set_resizable (GTK_WINDOW (dlg), FALSE);
273         gtk_widget_show_all (GTK_WIDGET (dlg));
274
275         gl_debug (DEBUG_FILE, "END");
276 }
277
278 /*---------------------------------------------------------------------------*/
279 /* PRIVATE.  Create widgets.                                                 */
280 /*---------------------------------------------------------------------------*/
281 static void
282 create_properties_dialog_widgets (glHigDialog *dlg,
283                                   glLabel     *label)
284 {
285         GtkWidget  *wframe, *template_entry, *rotate_sel;
286         glTemplate *template;
287         gboolean    rotate_flag;
288
289         gl_debug (DEBUG_FILE, "START");
290
291         wframe = gl_hig_category_new (_("Media Type"));
292         gl_hig_dialog_add_widget (dlg, wframe);
293
294         template_entry = gl_wdgt_media_select_new ();
295         gl_hig_category_add_widget (GL_HIG_CATEGORY(wframe), template_entry);
296
297         wframe = gl_hig_category_new (_("Label orientation"));
298         gl_hig_dialog_add_widget (dlg, wframe);
299
300         rotate_sel = gl_wdgt_rotate_label_new ();
301         gl_hig_category_add_widget (GL_HIG_CATEGORY(wframe), rotate_sel);
302
303         g_object_set_data (G_OBJECT (dlg), "template_entry", template_entry);
304         g_object_set_data (G_OBJECT (dlg), "rotate_sel", rotate_sel);
305
306         g_signal_connect (G_OBJECT (template_entry), "changed",
307                           G_CALLBACK (properties_template_changed), rotate_sel);
308
309         template = gl_label_get_template (label);
310         rotate_flag = gl_label_get_rotate_flag (label);
311
312         gl_debug (DEBUG_FILE, "%s, %s", template->page_size, template->name);
313
314         if (template->page_size != NULL) {
315                 gl_wdgt_media_select_set_page_size (GL_WDGT_MEDIA_SELECT (template_entry),
316                                                     template->page_size);
317         }
318         if (template->name != NULL) {
319                 gchar *template_name = gl_template_get_name_with_desc (template);
320                 gl_wdgt_media_select_set_name (GL_WDGT_MEDIA_SELECT (template_entry),
321                                                template_name);
322                 gl_wdgt_rotate_label_set_template_name (GL_WDGT_ROTATE_LABEL
323                                                         (rotate_sel), template_name);
324                 g_free (template_name);
325         } else {
326                 sheet_name =
327                     gl_wdgt_media_select_get_name (GL_WDGT_MEDIA_SELECT (template_entry));
328                 gl_wdgt_rotate_label_set_template_name (GL_WDGT_ROTATE_LABEL
329                                                         (rotate_sel), sheet_name);
330         }
331         gl_wdgt_rotate_label_set_state (GL_WDGT_ROTATE_LABEL (rotate_sel), rotate_flag);
332
333         gl_debug (DEBUG_FILE, "END");
334 }
335
336 /*---------------------------------------------------------------------------*/
337 /* PRIVATE.  Properties template changed callback.                           */
338 /*---------------------------------------------------------------------------*/
339 static void
340 properties_template_changed (glWdgtMediaSelect *select,
341                              gpointer           data)
342 {
343         glWdgtRotateLabel *rotate_sel = GL_WDGT_ROTATE_LABEL (data);
344         gchar             *name;
345
346         gl_debug (DEBUG_FILE, "START");
347
348         name = gl_wdgt_media_select_get_name (GL_WDGT_MEDIA_SELECT (select));
349
350         gl_wdgt_rotate_label_set_template_name (GL_WDGT_ROTATE_LABEL (rotate_sel),
351                                                 name);
352
353         g_free (name);
354
355         gl_debug (DEBUG_FILE, "END");
356 }
357
358 /*---------------------------------------------------------------------------*/
359 /* PRIVATE.  Properties "ok" button callback.                                */
360 /*---------------------------------------------------------------------------*/
361 static void
362 properties_response (GtkDialog *dlg,
363                      gint       response,
364                      gpointer   user_data)
365 {
366         GtkWidget  *template_entry, *rotate_sel;
367         glTemplate *template;
368         glLabel    *label;
369         gint        ret;
370         glWindow   *window;
371
372         gl_debug (DEBUG_FILE, "START");
373
374         switch (response) {
375         case GTK_RESPONSE_OK:
376                 template_entry =
377                         GTK_WIDGET (g_object_get_data (G_OBJECT (dlg),
378                                                        "template_entry"));
379                 rotate_sel = GTK_WIDGET (g_object_get_data (G_OBJECT (dlg),
380                                                             "rotate_sel"));
381
382                 if (page_size != NULL)
383                         g_free (page_size);
384                 page_size =
385                         gl_wdgt_media_select_get_page_size (GL_WDGT_MEDIA_SELECT (template_entry));
386
387                 if (sheet_name != NULL)
388                         g_free (sheet_name);
389                 sheet_name =
390                         gl_wdgt_media_select_get_name (GL_WDGT_MEDIA_SELECT (template_entry));
391
392                 rotate_flag =
393                         gl_wdgt_rotate_label_get_state (GL_WDGT_ROTATE_LABEL (rotate_sel));
394
395                 template = gl_template_from_name (sheet_name);
396
397                 label = GL_LABEL(g_object_get_data (G_OBJECT (dlg), "label"));
398                 gl_label_set_template (label, template);
399                 gl_label_set_rotate_flag (label, rotate_flag);
400
401                 break;
402         }
403
404         gtk_widget_destroy (GTK_WIDGET (dlg));
405
406         gl_debug (DEBUG_FILE, "END");
407 }
408
409 /*****************************************************************************/
410 /* "Open" menu callback.                                                     */
411 /*****************************************************************************/
412 void
413 gl_file_open (GtkWindow *window)
414 {
415         GtkFileSelection *fsel;
416
417         gl_debug (DEBUG_FILE, "START");
418
419         g_return_if_fail (window != NULL);
420
421         fsel = GTK_FILE_SELECTION (gtk_file_selection_new (_("Open")));
422         gtk_window_set_transient_for (GTK_WINDOW (fsel), window);
423         gtk_window_set_title (GTK_WINDOW (fsel), _("Open label"));
424
425         g_object_set_data (G_OBJECT (fsel), "parent_window", window);
426
427         g_signal_connect (G_OBJECT (fsel->ok_button), "clicked",
428                           G_CALLBACK (open_ok), fsel);
429
430         g_signal_connect_swapped (G_OBJECT (fsel->cancel_button), "clicked",
431                                   G_CALLBACK (gtk_widget_destroy),
432                                   G_OBJECT (fsel));
433
434         /* Recover state of open dialog */
435         if (open_path != NULL) {
436                 gtk_file_selection_set_filename (fsel, open_path);
437         }
438
439         /* show the dialog */
440         gtk_widget_show (GTK_WIDGET (fsel));
441
442         gl_debug (DEBUG_FILE, "END");
443 }
444
445 /*---------------------------------------------------------------------------*/
446 /* PRIVATE.  Open "O.K." button callback.                                    */
447 /*---------------------------------------------------------------------------*/
448 static void
449 open_ok (GtkWidget        *widget,
450          GtkFileSelection *fsel)
451 {
452         gchar            *filename;
453         GtkWidget        *dlg;
454         gint              ret;
455         GnomeRecentModel *recent;
456         GtkWindow        *window;
457
458         gl_debug (DEBUG_FILE, "START");
459
460         g_return_if_fail (GTK_IS_FILE_SELECTION (fsel));
461
462         /* get the filename */
463         filename = g_strdup (gtk_file_selection_get_filename (fsel));
464
465         if (!filename || g_file_test (filename, G_FILE_TEST_IS_DIR)) {
466
467                 dlg = gl_hig_alert_new (GTK_WINDOW(fsel),
468                                         GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
469                                         GTK_MESSAGE_WARNING,
470                                         GTK_BUTTONS_CLOSE,
471                                         _("Empty file name selection"),
472                                         _("Please select a file or supply a valid file name"));
473
474                 gtk_dialog_run (GTK_DIALOG (dlg));
475                 gtk_widget_destroy (dlg);
476
477         } else {
478
479                 if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR)) {
480
481                         dlg = gl_hig_alert_new (GTK_WINDOW(fsel),
482                                                 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
483                                                 GTK_MESSAGE_WARNING,
484                                                 GTK_BUTTONS_CLOSE,
485                                                 _("File does not exist"),
486                                                 _("Please select a file or supply a valid file name"));
487
488                         gtk_dialog_run (GTK_DIALOG (dlg));
489                         gtk_widget_destroy (dlg);
490
491
492                 } else {
493                 
494                         window = g_object_get_data (G_OBJECT(fsel),
495                                                     "parent_window");
496
497                         if ( gl_file_open_real (filename, window) ) {
498                                 gtk_widget_destroy (GTK_WIDGET (fsel));
499                         }
500
501                 }
502
503         }
504
505         g_free (filename);
506
507         gl_debug (DEBUG_FILE, "END");
508 }
509
510 /*****************************************************************************/
511 /* "Open recent" menu callback.                                              */
512 /*****************************************************************************/
513 gboolean
514 gl_file_open_recent (GnomeRecentView *view,
515                      const gchar     *filename,
516                      GtkWindow       *window)
517 {
518         gl_debug (DEBUG_FILE, "");
519
520         return gl_file_open_real (filename, window);
521 }
522
523 /*---------------------------------------------------------------------------*/
524 /* PRIVATE.  Open a file.                                                    */
525 /*---------------------------------------------------------------------------*/
526 gboolean
527 gl_file_open_real (const gchar     *filename,
528                    GtkWindow       *window)
529 {
530         gchar            *abs_filename;
531         glLabel          *label;
532         glXMLLabelStatus  status;
533         GnomeRecentModel *recent;
534         gint              ret;
535         GtkWidget        *new_window;
536
537         gl_debug (DEBUG_FILE, "START");
538
539         abs_filename = gl_util_make_absolute (filename);
540         label = gl_xml_label_open (abs_filename, &status);
541         if (!label) {
542                 GtkWidget *dlg;
543                 gchar *primary_msg;
544
545                 gl_debug (DEBUG_FILE, "couldn't open file");
546
547                 primary_msg = g_strdup_printf (_("Could not open file \"%s\""),
548                                                filename);
549
550                 dlg = gl_hig_alert_new (window,
551                                         GTK_DIALOG_DESTROY_WITH_PARENT,
552                                         GTK_MESSAGE_ERROR,
553                                         GTK_BUTTONS_CLOSE,
554                                         primary_msg,
555                                         _("Not a supported file format"));
556
557                 g_free (primary_msg);
558
559                 gtk_dialog_run (GTK_DIALOG (dlg));
560                 gtk_widget_destroy (dlg);
561
562                 g_free (abs_filename);
563
564                 gl_debug (DEBUG_FILE, "END false");
565
566                 return FALSE;
567
568         } else {
569
570                 if ( gl_window_is_empty (GL_WINDOW(window)) ) {
571                         gl_window_set_label (GL_WINDOW(window), label);
572                 } else {
573                         new_window = gl_window_new_from_label (label);
574                         gtk_widget_show_all (new_window);
575                 }
576
577                 recent = gl_recent_get_model ();
578                 gnome_recent_model_add (recent, abs_filename);
579
580                 if (open_path != NULL)
581                         g_free (open_path);
582                 open_path = g_path_get_dirname (abs_filename);
583                 if (open_path != NULL)
584                         open_path = g_strconcat (open_path, "/", NULL);
585
586                 g_free (abs_filename);
587
588                 gl_debug (DEBUG_FILE, "END true");
589
590                 return TRUE;
591
592         }
593 }
594
595 /*****************************************************************************/
596 /* "Save" menu callback.                                                     */
597 /*****************************************************************************/
598 gboolean
599 gl_file_save (glLabel   *label,
600               GtkWindow *window)
601 {
602         glXMLLabelStatus  status;
603         GError           *error = NULL;
604         gchar            *filename = NULL;
605         GnomeRecentModel *recent;
606
607         gl_debug (DEBUG_FILE, "");
608
609         g_return_val_if_fail (label != NULL, FALSE);
610         
611         if (gl_label_is_untitled (label))
612         {
613                 gl_debug (DEBUG_FILE, "Untitled");
614
615                 return gl_file_save_as (label, window);
616         }
617
618         if (!gl_label_is_modified (label))      
619         {
620                 gl_debug (DEBUG_FILE, "Not modified");
621
622                 return TRUE;
623         }
624         
625         filename = gl_label_get_filename (label);
626         g_return_val_if_fail (filename != NULL, FALSE);
627         
628         gl_xml_label_save (label, filename, &status);
629
630         if (status != XML_LABEL_OK)
631         {
632                 GtkWidget *dialog;
633                 gchar *primary_msg;
634
635                 gl_debug (DEBUG_FILE, "FAILED");
636
637                 primary_msg = g_strdup_printf (_("Could not save file \"%s\""),
638                                                filename);
639
640                 dialog = gl_hig_alert_new (window,
641                                            GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
642                                            GTK_MESSAGE_ERROR,
643                                            GTK_BUTTONS_CLOSE,
644                                            primary_msg,
645                                            _("Error encountered during save.  The file is still not saved."));
646
647                 g_free (primary_msg);
648
649                 gtk_dialog_run (GTK_DIALOG (dialog));
650                 gtk_widget_destroy (dialog);
651
652                 g_free (filename);
653
654                 return FALSE;
655         }       
656         else
657         {
658                 gl_debug (DEBUG_FILE, "OK");
659
660                 recent = gl_recent_get_model ();
661                 gnome_recent_model_add (recent, filename);
662
663                 g_free (filename);
664
665                 return TRUE;
666         }
667 }
668
669 /*****************************************************************************/
670 /* "Save As" menu callback.                                                  */
671 /*****************************************************************************/
672 gboolean
673 gl_file_save_as (glLabel   *label,
674                  GtkWindow *window)
675 {
676         GtkFileSelection *fsel;
677         gboolean          saved_flag = FALSE;
678         gboolean          destroy_flag = FALSE;
679         gchar            *name, *title;
680
681         gl_debug (DEBUG_FILE, "START");
682
683         g_return_val_if_fail (label && GL_IS_LABEL(label), FALSE);
684         g_return_val_if_fail (window && GTK_IS_WINDOW(window), FALSE);
685
686         name = gl_label_get_short_name (label);
687         title = g_strdup_printf (_("Save \"%s\" as"), name);
688         g_free (name);
689
690         fsel = GTK_FILE_SELECTION (gtk_file_selection_new (title));
691         gtk_window_set_modal (GTK_WINDOW (fsel), TRUE);
692         gtk_window_set_transient_for (GTK_WINDOW (fsel), window);
693
694         g_object_set_data (G_OBJECT (fsel), "label", label);
695         g_object_set_data (G_OBJECT (fsel), "saved_flag", &saved_flag);
696
697         g_signal_connect (G_OBJECT (fsel->ok_button), "clicked",
698                           G_CALLBACK (save_as_ok_cb), fsel);
699
700         g_signal_connect (G_OBJECT (fsel->cancel_button), "clicked",
701                           G_CALLBACK (save_as_cancel_cb), fsel);
702
703         g_signal_connect (G_OBJECT (fsel), "destroy",
704                           G_CALLBACK (save_as_destroy_cb), &destroy_flag);
705
706         /* Recover proper state of save-as dialog */
707         if (save_path != NULL) {
708                 gtk_file_selection_set_filename (fsel, save_path);
709         }
710
711         /* show the dialog */
712         gtk_widget_show (GTK_WIDGET (fsel));
713
714         /* Hold here and process events until we are done with this dialog. */
715         gtk_main ();
716
717         /* Destroy dialog if not already destroyed. */
718         if (!destroy_flag) {
719                 /* Disconnect our destroy callback first, so that we don't
720                  * kill the current gtk_main() loop. */
721                 g_signal_handlers_disconnect_by_func (GTK_OBJECT (fsel),
722                                                       G_CALLBACK (save_as_destroy_cb),
723                                                       &destroy_flag);
724                 gtk_widget_destroy (GTK_WIDGET (fsel));
725         }
726
727         g_free (title);
728
729         gl_debug (DEBUG_FILE, "END");
730
731         /* Return flag as set by one of the above callbacks, TRUE = saved */
732         return saved_flag;
733 }
734
735 /*---------------------------------------------------------------------------*/
736 /* PRIVATE.  "Save As" ok button callback.                                   */
737 /*---------------------------------------------------------------------------*/
738 static void
739 save_as_ok_cb (GtkWidget        *widget,
740                GtkFileSelection *fsel)
741 {
742         gchar            *raw_filename, *filename;
743         GtkWidget        *dlg;
744         glLabel          *label;
745         glXMLLabelStatus  status;
746         GnomeRecentModel *recent;
747         gboolean         *saved_flag;
748         gchar            *primary_msg;
749         gboolean          cancel_flag = FALSE;
750
751         gl_debug (DEBUG_FILE, "START");
752
753         g_return_if_fail (GTK_IS_FILE_SELECTION (fsel));
754
755         label = g_object_get_data (G_OBJECT(fsel), "label");
756         saved_flag = g_object_get_data (G_OBJECT(fsel), "saved_flag");
757
758         /* get the filename */
759         raw_filename = g_strdup (gtk_file_selection_get_filename (fsel));
760
761         gl_debug (DEBUG_FILE, "raw_filename = \"%s\"", raw_filename);
762
763         if (!raw_filename || g_file_test (raw_filename, G_FILE_TEST_IS_DIR)) {
764
765                 dlg = gl_hig_alert_new (GTK_WINDOW(fsel),
766                                         GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
767                                         GTK_MESSAGE_WARNING,
768                                         GTK_BUTTONS_CLOSE,
769                                         _("Empty file name selection"),
770                                         _("Please supply a valid file name"));
771
772                 gtk_dialog_run (GTK_DIALOG (dlg));
773                 gtk_widget_destroy (dlg);
774
775         } else {
776
777                 filename = gl_util_add_extension (raw_filename);
778
779                 gl_debug (DEBUG_FILE, "filename = \"%s\"", filename);
780
781                 if (g_file_test (filename, G_FILE_TEST_IS_REGULAR)) {
782                         gint ret;
783
784                         primary_msg = g_strdup_printf (_("Overwrite file \"%s\"?"),
785                                                        filename);
786
787                         dlg = gl_hig_alert_new (GTK_WINDOW(fsel),
788                                                 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
789                                                 GTK_MESSAGE_QUESTION,
790                                                 GTK_BUTTONS_YES_NO,
791                                                 primary_msg,
792                                                 _("File already exists."));
793                         
794                         g_free (primary_msg);
795
796                         ret = gtk_dialog_run (GTK_DIALOG (dlg));
797                         if ( ret == GTK_RESPONSE_NO ) {
798                                 cancel_flag = TRUE;
799                         }
800                         gtk_widget_destroy (dlg);
801                 }
802
803                 if (!cancel_flag) {
804
805                         gl_xml_label_save (label, filename, &status);
806
807                         gl_debug (DEBUG_FILE, "status of save = %d", status);
808
809                         if ( status != XML_LABEL_OK ) {
810
811                                 primary_msg = g_strdup_printf (_("Could not save file \"%s\""),
812                                                                filename);
813
814                                 dlg = gl_hig_alert_new (GTK_WINDOW(fsel),
815                                                         GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
816                                                         GTK_MESSAGE_ERROR,
817                                                         GTK_BUTTONS_CLOSE,
818                                                         primary_msg,
819                                                         _("Error encountered during save.  The file is still not saved."));
820
821                                 g_free (primary_msg);
822
823                                 gtk_dialog_run (GTK_DIALOG (dlg));
824                                 gtk_widget_destroy (dlg);
825
826                         } else {
827
828                                 *saved_flag = TRUE;
829
830                                 recent = gl_recent_get_model ();
831                                 gnome_recent_model_add (recent, filename);
832
833                                 if (save_path != NULL)
834                                         g_free (save_path);
835                                 save_path = g_path_get_dirname (filename);
836                                 if (save_path != NULL)
837                                         save_path = g_strconcat (save_path, "/", NULL);
838
839                                 gtk_widget_destroy (GTK_WIDGET (fsel));
840                         }
841
842                 }
843
844                 g_free (filename);
845         }
846
847         g_free (raw_filename);
848
849         gl_debug (DEBUG_FILE, "END");
850 }
851
852 /*---------------------------------------------------------------------------*/
853 /* PRIVATE.  "Save As" cancel button callback.                               */
854 /*---------------------------------------------------------------------------*/
855 static void
856 save_as_cancel_cb (GtkWidget        *widget,
857                    GtkFileSelection *fsel)
858 {
859         gboolean *saved_flag = g_object_get_data (G_OBJECT (fsel), "saved_flag");
860
861         g_return_if_fail (GTK_IS_FILE_SELECTION (fsel));
862
863         *saved_flag = FALSE;
864         gtk_widget_hide (GTK_WIDGET (fsel));
865         gtk_main_quit ();
866 }
867
868 /*---------------------------------------------------------------------------*/
869 /* PRIVATE.  "Save As" destroy callback.                                     */
870 /*---------------------------------------------------------------------------*/
871 static void
872 save_as_destroy_cb (GtkWidget *widget,
873                     gboolean  *destroy_flag)
874 {
875         *destroy_flag = TRUE;
876         gtk_main_quit ();
877 }
878
879
880 /*****************************************************************************/
881 /* "Close" menu callback.                                                    */
882 /*****************************************************************************/
883 gboolean
884 gl_file_close (glWindow *window)
885 {
886         glView  *view;
887         glLabel *label;
888         gboolean close = TRUE;
889
890         gl_debug (DEBUG_FILE, "START");
891
892         g_return_val_if_fail (window && GL_IS_WINDOW(window), TRUE);
893
894         if ( !gl_window_is_empty (window) ) {
895
896                 view = GL_VIEW(window->view);
897                 label = view->label;
898
899                 if (gl_label_is_modified (label))       {
900                         GtkWidget *msgbox, *w;
901                         gchar *fname = NULL, *msg = NULL;
902                         gint ret;
903                         gboolean exiting;
904
905                         fname = gl_label_get_short_name (label);
906                         
907                         msg = g_strdup_printf (_("Save changes to document \"%s\" before closing?"),
908                                                fname);
909                         
910                         msgbox = gl_hig_alert_new (GTK_WINDOW(window),
911                                                    GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
912                                                    GTK_MESSAGE_WARNING,
913                                                    GTK_BUTTONS_NONE,
914                                                    msg,
915                                                    _("Your changes will be lost if you don't save them."));
916
917                         gtk_dialog_add_button (GTK_DIALOG (msgbox),
918                                                _("Close without saving"),
919                                                GTK_RESPONSE_NO);
920
921                         gtk_dialog_add_button (GTK_DIALOG (msgbox),
922                                                GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
923
924                         gtk_dialog_add_button (GTK_DIALOG (msgbox),
925                                                GTK_STOCK_SAVE, GTK_RESPONSE_YES);
926
927                         gtk_dialog_set_default_response (GTK_DIALOG (msgbox), GTK_RESPONSE_YES);
928
929                         gtk_window_set_resizable (GTK_WINDOW (msgbox), FALSE);
930
931                         ret = gtk_dialog_run (GTK_DIALOG (msgbox));
932                 
933                         gtk_widget_destroy (msgbox);
934
935                         g_free (fname);
936                         g_free (msg);
937                 
938                         switch (ret)
939                         {
940                         case GTK_RESPONSE_YES:
941                                 close = gl_file_save (label,
942                                                       GTK_WINDOW(window));
943                                 break;
944                         case GTK_RESPONSE_NO:
945                                 close = TRUE;
946                                 break;
947                         default:
948                                 close = FALSE;
949                         }
950
951                         gl_debug (DEBUG_FILE, "CLOSE: %s", close ? "TRUE" : "FALSE");
952                 }
953
954         }
955
956         if (close) {
957                 gtk_widget_destroy (GTK_WIDGET(window));
958
959                 if ( gl_window_get_window_list () == NULL ) {
960                         
961                         gl_debug (DEBUG_FILE, "All windows closed.");
962         
963                         bonobo_main_quit ();
964                 }
965
966         }
967
968         gl_debug (DEBUG_FILE, "END");
969
970         return close;
971 }
972
973 /*****************************************************************************/
974 /* "Exit" menu callback.                                                     */
975 /*****************************************************************************/
976 void
977 gl_file_exit (void)
978 {
979         const GList *window_list;
980         GList       *p, *p_next;
981
982         gl_debug (DEBUG_FILE, "START");
983
984         window_list = gl_window_get_window_list ();
985
986         for (p=(GList *)window_list; p != NULL; p=p_next) {
987                 p_next = p->next;
988
989                 gl_file_close (GL_WINDOW(p->data));
990         }
991
992         gl_debug (DEBUG_FILE, "END");
993 }