]> git.sur5r.net Git - glabels/blob - glabels2/src/file.c
Initial revision
[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 "glabels.h"
29 #include "xml-label.h"
30 #include "file.h"
31 #include "mdi.h"
32 #include "recent.h"
33 #include "util.h"
34 #include "wdgt-media-select.h"
35 #include "wdgt-rotate-label.h"
36 #include "debug.h"
37
38 /*===========================================*/
39 /* Private globals                           */
40 /*===========================================*/
41
42 /* Saved state for new dialog */
43 static gchar *page_size = NULL;
44 static gchar *sheet_name = NULL;
45 static gboolean rotate_flag = FALSE;
46
47 /* Saved state of file selectors */
48 static gchar *open_path = NULL;
49 static gchar *save_path = NULL;
50
51 /*===========================================*/
52 /* Local function prototypes.                */
53 /*===========================================*/
54 static void create_new_dialog_widgets (GtkDialog *dlg);
55 static void new_template_changed (glWdgtMediaSelect *select,
56                                   gpointer data);
57 static void new_response (GtkDialog *dlg,
58                           gint      response,
59                           gpointer  user_data);
60 static void open_ok (GtkWidget * widget,
61                      GtkFileSelection * fsel);
62
63 static void save_as_ok_cb (GtkWidget * widget, GtkFileSelection * fsel);
64 static void save_as_cancel_cb (GtkWidget * widget, GtkFileSelection * fsel);
65 static void save_as_destroy_cb (GtkWidget * widget, gboolean * destroy_flag);
66
67 \f
68 /*****************************************************************************/
69 /* "New" menu callback.                                                      */
70 /*****************************************************************************/
71 void
72 gl_file_new (void)
73 {
74         GtkWidget *dlg;
75         BonoboWindow *win = glabels_get_active_window ();
76
77         gl_debug (DEBUG_FILE, "START");
78
79         g_return_if_fail (glabels_mdi != NULL);
80         g_return_if_fail (win != NULL);
81
82         dlg = gtk_dialog_new_with_buttons (_("New Label or Card"),
83                                            GTK_WINDOW (win),
84                                            GTK_DIALOG_DESTROY_WITH_PARENT,
85                                            GTK_STOCK_OK, GTK_RESPONSE_OK,
86                                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
87                                            NULL);
88
89         create_new_dialog_widgets (GTK_DIALOG (dlg));
90
91         g_signal_connect (G_OBJECT(dlg), "response",
92                           G_CALLBACK (new_response), dlg);
93
94         gtk_widget_show_all (GTK_WIDGET (dlg));
95
96         gl_debug (DEBUG_FILE, "END");
97 }
98
99 /*---------------------------------------------------------------------------*/
100 /* PRIVATE.  Create widgets.                                                 */
101 /*---------------------------------------------------------------------------*/
102 static void
103 create_new_dialog_widgets (GtkDialog * dlg)
104 {
105         GtkWidget *wframe, *wvbox, *template_entry, *rotate_sel;
106
107         gl_debug (DEBUG_FILE, "START");
108
109         wframe = gtk_frame_new (_("Media Type"));
110         gtk_box_pack_start (GTK_BOX (dlg->vbox), wframe, FALSE, FALSE, 0);
111
112         wvbox = gtk_vbox_new (FALSE, GNOME_PAD);
113         gtk_container_set_border_width (GTK_CONTAINER (wvbox), 10);
114         gtk_container_add (GTK_CONTAINER (wframe), wvbox);
115
116         template_entry = gl_wdgt_media_select_new ();
117         gtk_container_add (GTK_CONTAINER (wvbox), template_entry);
118
119         wframe = gtk_frame_new (_("Label orientation"));
120         gtk_box_pack_start (GTK_BOX (dlg->vbox), wframe, FALSE, FALSE, 0);
121
122         wvbox = gtk_vbox_new (FALSE, GNOME_PAD);
123         gtk_container_set_border_width (GTK_CONTAINER (wvbox), 10);
124         gtk_container_add (GTK_CONTAINER (wframe), wvbox);
125
126         rotate_sel = gl_wdgt_rotate_label_new ();
127         gtk_box_pack_start (GTK_BOX (wvbox), rotate_sel, FALSE, FALSE, 0);
128
129         g_object_set_data (G_OBJECT (dlg), "template_entry",
130                              template_entry);
131         g_object_set_data (G_OBJECT (dlg), "rotate_sel", rotate_sel);
132
133         g_signal_connect (G_OBJECT (template_entry), "changed",
134                           G_CALLBACK (new_template_changed), rotate_sel);
135
136         if (page_size != NULL) {
137                 gl_wdgt_media_select_set_page_size (GL_WDGT_MEDIA_SELECT (template_entry),
138                                                page_size);
139         }
140         if (sheet_name != NULL) {
141                 gl_wdgt_media_select_set_name (GL_WDGT_MEDIA_SELECT (template_entry),
142                                           sheet_name);
143                 gl_wdgt_rotate_label_set_template_name (GL_WDGT_ROTATE_LABEL
144                                                     (rotate_sel), sheet_name);
145         } else {
146                 sheet_name =
147                     gl_wdgt_media_select_get_name (GL_WDGT_MEDIA_SELECT (template_entry));
148                 gl_wdgt_rotate_label_set_template_name (GL_WDGT_ROTATE_LABEL
149                                                     (rotate_sel), sheet_name);
150         }
151         gl_wdgt_rotate_label_set_state (GL_WDGT_ROTATE_LABEL (rotate_sel), rotate_flag);
152
153         gl_debug (DEBUG_FILE, "END");
154 }
155
156 /*---------------------------------------------------------------------------*/
157 /* PRIVATE.  New template changed callback.                                  */
158 /*---------------------------------------------------------------------------*/
159 static void
160 new_template_changed (glWdgtMediaSelect * select,
161                       gpointer data)
162 {
163         glWdgtRotateLabel *rotate_sel = GL_WDGT_ROTATE_LABEL (data);
164         gchar *name;
165
166         gl_debug (DEBUG_FILE, "START");
167
168         name = gl_wdgt_media_select_get_name (GL_WDGT_MEDIA_SELECT (select));
169
170         gl_wdgt_rotate_label_set_template_name (GL_WDGT_ROTATE_LABEL (rotate_sel),
171                                             name);
172
173         g_free (name);
174
175         gl_debug (DEBUG_FILE, "END");
176 }
177
178 /*---------------------------------------------------------------------------*/
179 /* PRIVATE.  New "ok" button callback.                                       */
180 /*---------------------------------------------------------------------------*/
181 static void
182 new_response (GtkDialog *dlg,
183               gint      response,
184               gpointer  user_data)
185 {
186         GtkWidget *template_entry, *rotate_sel;
187         glMDIChild *new_child = NULL;
188         gint ret;
189
190         gl_debug (DEBUG_FILE, "START");
191
192         switch (response) {
193         case GTK_RESPONSE_OK:
194                 template_entry =
195                         GTK_WIDGET (g_object_get_data (G_OBJECT (dlg),
196                                                          "template_entry"));
197                 rotate_sel = GTK_WIDGET (g_object_get_data (G_OBJECT (dlg),
198                                                               "rotate_sel"));
199
200                 if (page_size != NULL)
201                         g_free (page_size);
202                 page_size =
203                         gl_wdgt_media_select_get_page_size (GL_WDGT_MEDIA_SELECT (template_entry));
204
205                 if (sheet_name != NULL)
206                         g_free (sheet_name);
207                 sheet_name =
208                         gl_wdgt_media_select_get_name (GL_WDGT_MEDIA_SELECT (template_entry));
209
210                 rotate_flag =
211                         gl_wdgt_rotate_label_get_state (GL_WDGT_ROTATE_LABEL (rotate_sel));
212
213                 new_child = gl_mdi_child_new (sheet_name, rotate_flag);
214                 gl_debug (DEBUG_FILE, "template set.");
215
216                 ret = bonobo_mdi_add_child (BONOBO_MDI (glabels_mdi),
217                                             BONOBO_MDI_CHILD (new_child));
218                 g_return_if_fail (ret != FALSE);
219                 gl_debug (DEBUG_FILE, "Child added.");
220
221                 ret = bonobo_mdi_add_view (BONOBO_MDI (glabels_mdi),
222                                            BONOBO_MDI_CHILD (new_child));
223                 g_return_if_fail (ret != FALSE);
224                 gl_debug (DEBUG_FILE, "View added.");
225
226                 gtk_widget_grab_focus (GTK_WIDGET (glabels_get_active_view ()));
227                 break;
228         }
229
230         gtk_widget_destroy (GTK_WIDGET (dlg));
231
232         gl_debug (DEBUG_FILE, "END");
233 }
234
235 /*****************************************************************************/
236 /* "Open" menu callback.                                                     */
237 /*****************************************************************************/
238 void
239 gl_file_open (glMDIChild *active_child)
240 {
241         GtkFileSelection *fsel;
242         BonoboWindow *app = glabels_get_active_window ();
243
244         gl_debug (DEBUG_FILE, "START");
245
246         g_return_if_fail (app != NULL);
247
248         fsel = GTK_FILE_SELECTION (gtk_file_selection_new (_("Open")));
249         gtk_window_set_transient_for (GTK_WINDOW (fsel), GTK_WINDOW (app));
250         gtk_window_set_title (GTK_WINDOW (fsel), _("Open label"));
251
252         g_signal_connect (G_OBJECT (fsel->ok_button), "clicked",
253                           G_CALLBACK (open_ok), fsel);
254
255         g_signal_connect_swapped (G_OBJECT (fsel->cancel_button), "clicked",
256                                   G_CALLBACK (gtk_widget_destroy),
257                                   G_OBJECT (fsel));
258
259         /* Recover state of open dialog */
260         if (open_path != NULL) {
261                 gtk_file_selection_set_filename (fsel, open_path);
262         }
263
264         /* show the dialog */
265         gtk_widget_show (GTK_WIDGET (fsel));
266
267         gl_debug (DEBUG_FILE, "END");
268 }
269
270 /*---------------------------------------------------------------------------*/
271 /* PRIVATE.  Open "O.K." button callback.                                    */
272 /*---------------------------------------------------------------------------*/
273 static void
274 open_ok (GtkWidget * widget,
275          GtkFileSelection * fsel)
276 {
277         gchar *filename;
278         GtkWidget *dlg;
279         glMDIChild *new_child = NULL;
280         gint ret;
281         GnomeRecentModel *recent;
282
283         gl_debug (DEBUG_FILE, "START");
284
285         g_return_if_fail (GTK_IS_FILE_SELECTION (fsel));
286
287         /* get the filename */
288         filename = g_strdup (gtk_file_selection_get_filename (fsel));
289         if (filename) {
290                 if ( gl_file_open_real (filename, GTK_WINDOW(fsel)) ) {
291                         gtk_widget_destroy (GTK_WIDGET (fsel));
292                 }
293         }
294
295         g_free (filename);
296
297         gl_debug (DEBUG_FILE, "END");
298 }
299
300 /*****************************************************************************/
301 /* "Open recent" menu callback.                                              */
302 /*****************************************************************************/
303 gboolean
304 gl_file_open_recent (GnomeRecentView *view,
305                      const gchar     *filename,
306                      BonoboWindow    *win)
307 {
308         gl_debug (DEBUG_FILE, "");
309
310         return gl_file_open_real (filename, GTK_WINDOW(win));
311 }
312
313 /*---------------------------------------------------------------------------*/
314 /* PRIVATE.  Open a file.                                                    */
315 /*---------------------------------------------------------------------------*/
316 gboolean
317 gl_file_open_real (const gchar     *filename,
318                    GtkWindow       *win)
319 {
320         gchar *abs_filename;
321         glMDIChild *new_child = NULL;
322         GtkWidget *dlg;
323         GnomeRecentModel *recent;
324         gint ret;
325
326         gl_debug (DEBUG_FILE, "START");
327
328         abs_filename = gl_util_make_absolute (filename);
329         new_child = gl_mdi_child_new_with_uri (filename, NULL);
330         if (!new_child) {
331
332                 gl_debug (DEBUG_FILE, "couldn't open file");
333
334                 dlg = gtk_message_dialog_new (GTK_WINDOW(win),
335                                               GTK_DIALOG_DESTROY_WITH_PARENT,
336                                               GTK_MESSAGE_ERROR,
337                                               GTK_BUTTONS_CLOSE,
338                                               _("Cannot open file '%s'"),
339                                               filename);
340                 gtk_dialog_run (GTK_DIALOG (dlg));
341                 gtk_widget_destroy (dlg);
342
343                 g_free (abs_filename);
344
345                 gl_debug (DEBUG_FILE, "END false");
346
347                 return FALSE;
348
349         } else {
350
351                 ret = bonobo_mdi_add_child (BONOBO_MDI (glabels_mdi),
352                                             BONOBO_MDI_CHILD (new_child));
353                 g_return_if_fail (ret != FALSE);
354                 gl_debug (DEBUG_FILE, "Child added.");
355
356                 ret = bonobo_mdi_add_view (BONOBO_MDI (glabels_mdi),
357                                            BONOBO_MDI_CHILD (new_child));
358                 g_return_if_fail (ret != FALSE);
359                 gl_debug (DEBUG_FILE, "View added.");
360
361                 gtk_widget_grab_focus (GTK_WIDGET (glabels_get_active_view ()));
362
363                 recent = gl_recent_get_model ();
364                 gnome_recent_model_add (recent, abs_filename);
365
366                 if (open_path != NULL)
367                         g_free (open_path);
368                 open_path = g_path_get_dirname (abs_filename);
369                 if (open_path != NULL)
370                         open_path = g_strconcat (open_path, "/", NULL);
371
372                 g_free (abs_filename);
373
374                 gl_debug (DEBUG_FILE, "END true");
375
376                 return TRUE;
377
378         }
379 }
380
381 /*****************************************************************************/
382 /* "Save" menu callback.                                                     */
383 /*****************************************************************************/
384 gboolean
385 gl_file_save (glMDIChild *child)
386 {
387         glXMLLabelStatus status;
388         glLabel *label = NULL;
389         GError *error = NULL;
390         gchar *filename = NULL;
391         GnomeRecentModel *recent;
392
393         gl_debug (DEBUG_FILE, "");
394
395         g_return_val_if_fail (child != NULL, FALSE);
396         
397         label = child->label;
398         g_return_val_if_fail (label != NULL, FALSE);
399         
400         if (gl_label_is_untitled (label))
401         {
402                 gl_debug (DEBUG_FILE, "Untitled");
403
404                 return gl_file_save_as (child);
405         }
406
407         if (!gl_label_is_modified (label))      
408         {
409                 gl_debug (DEBUG_FILE, "Not modified");
410
411                 return TRUE;
412         }
413         
414         filename = gl_label_get_filename (label);
415         g_return_val_if_fail (filename != NULL, FALSE);
416         
417         gl_xml_label_save (label, filename, &status);
418
419         if (status != XML_LABEL_OK)
420         {
421                 GtkWidget *dialog;
422
423                 gl_debug (DEBUG_FILE, "FAILED");
424
425                 dialog = gtk_message_dialog_new (GTK_WINDOW(glabels_get_active_window()),
426                                                  GTK_DIALOG_DESTROY_WITH_PARENT,
427                                                  GTK_MESSAGE_ERROR,
428                                                  GTK_BUTTONS_CLOSE,
429                                                  _("Error saving file '%s'"),
430                                                  filename);
431                 gtk_dialog_run (GTK_DIALOG (dialog));
432                 gtk_widget_destroy (dialog);
433
434                 g_free (filename);
435
436                 return FALSE;
437         }       
438         else
439         {
440                 gl_debug (DEBUG_FILE, "OK");
441
442                 recent = gl_recent_get_model ();
443                 gnome_recent_model_add (recent, filename);
444
445                 g_free (filename);
446
447                 return TRUE;
448         }
449 }
450
451 /*****************************************************************************/
452 /* "Save As" menu callback.                                                  */
453 /*****************************************************************************/
454 gboolean
455 gl_file_save_as (glMDIChild *child)
456 {
457         GtkFileSelection *fsel;
458         BonoboWindow *app = glabels_get_active_window ();
459         gboolean saved_flag = FALSE;
460         gboolean destroy_flag = FALSE;
461
462         gl_debug (DEBUG_FILE, "START");
463
464         g_return_val_if_fail (child != NULL, FALSE);
465         g_return_val_if_fail (app != NULL, FALSE);
466
467
468         fsel = GTK_FILE_SELECTION (gtk_file_selection_new (_("Save label as")));
469         gtk_window_set_modal (GTK_WINDOW (fsel), TRUE);
470         gtk_window_set_transient_for (GTK_WINDOW (fsel), GTK_WINDOW (app));
471
472         g_object_set_data (G_OBJECT (fsel), "child", child);
473         g_object_set_data (G_OBJECT (fsel), "saved_flag", &saved_flag);
474
475         g_signal_connect (G_OBJECT (fsel->ok_button), "clicked",
476                           G_CALLBACK (save_as_ok_cb), fsel);
477
478         g_signal_connect (G_OBJECT (fsel->cancel_button), "clicked",
479                           G_CALLBACK (save_as_cancel_cb), fsel);
480
481         g_signal_connect (G_OBJECT (fsel), "destroy",
482                           G_CALLBACK (save_as_destroy_cb), &destroy_flag);
483
484         /* Recover proper state of save-as dialog */
485         if (save_path != NULL) {
486                 gtk_file_selection_set_filename (fsel, save_path);
487         }
488
489         /* show the dialog */
490         gtk_widget_show (GTK_WIDGET (fsel));
491
492         /* Hold here and process events until we are done with this dialog. */
493         gtk_main ();
494
495         /* Destroy dialog if not already destroyed. */
496         if (!destroy_flag) {
497                 /* Disconnect our destroy callback first, so that we don't kill the
498                  * current gtk_main() loop. */
499                 g_signal_handlers_disconnect_by_func (GTK_OBJECT (fsel),
500                                                       G_CALLBACK (save_as_destroy_cb),
501                                                       &destroy_flag);
502                 gtk_widget_destroy (GTK_WIDGET (fsel));
503         }
504
505         gl_debug (DEBUG_FILE, "END");
506
507         /* Return flag as set by one of the above callbacks, TRUE = saved */
508         return saved_flag;
509 }
510
511 /*---------------------------------------------------------------------------*/
512 /* PRIVATE.  "Save As" ok button callback.                                   */
513 /*---------------------------------------------------------------------------*/
514 static void
515 save_as_ok_cb (GtkWidget * widget,
516                GtkFileSelection * fsel)
517 {
518         gchar *raw_filename, *filename;
519         GtkWidget *dlg;
520         glMDIChild *child;
521         glLabel *label;
522         glXMLLabelStatus status;
523         GnomeRecentModel *recent;
524         gboolean *saved_flag;
525
526         gl_debug (DEBUG_FILE, "START");
527
528         g_return_if_fail (GTK_IS_FILE_SELECTION (fsel));
529
530         child = g_object_get_data (G_OBJECT(fsel), "child");
531         saved_flag = g_object_get_data (G_OBJECT(fsel), "saved_flag");
532
533         g_return_if_fail (child != NULL);
534         g_return_if_fail (GL_IS_MDI_CHILD (child));
535         gl_debug (DEBUG_FILE, "Got child");
536
537         label = child->label;
538
539         /* get the filename */
540         raw_filename = g_strdup (gtk_file_selection_get_filename (fsel));
541
542         gl_debug (DEBUG_FILE, "raw_filename = \"%s\"", raw_filename);
543
544         if (!raw_filename || (raw_filename[strlen (raw_filename) - 1] == '/')) {
545
546                 dlg = gtk_message_dialog_new (GTK_WINDOW(fsel),
547                                               GTK_DIALOG_DESTROY_WITH_PARENT,
548                                               GTK_MESSAGE_WARNING,
549                                               GTK_BUTTONS_CLOSE,
550                                               _("Must supply file name"));
551                 gtk_window_set_modal (GTK_WINDOW (dlg), TRUE);
552
553         } else {
554
555                 filename = gl_util_add_extension (raw_filename);
556
557                 gl_debug (DEBUG_FILE, "filename = \"%s\"", filename);
558
559                 gl_xml_label_save (label, filename, &status);
560
561                 gl_debug (DEBUG_FILE, "status of save = %d", status);
562
563                 if ( status != XML_LABEL_OK ) {
564
565                         dlg = gtk_message_dialog_new (GTK_WINDOW(fsel),
566                                                       GTK_DIALOG_DESTROY_WITH_PARENT,
567                                                       GTK_MESSAGE_ERROR,
568                                                       GTK_BUTTONS_CLOSE,
569                                                       _("Error writing file '%s'"),
570                                                       filename);
571                         gtk_window_set_modal (GTK_WINDOW (dlg), TRUE);
572
573                 } else {
574
575                         *saved_flag = TRUE;
576
577                         recent = gl_recent_get_model ();
578                         gnome_recent_model_add (recent, filename);
579
580                         if (save_path != NULL)
581                                 g_free (save_path);
582                         save_path = g_path_get_dirname (filename);
583                         if (save_path != NULL)
584                                 save_path = g_strconcat (save_path, "/", NULL);
585
586                         gtk_widget_destroy (GTK_WIDGET (fsel));
587                 }
588
589                 g_free (filename);
590         }
591
592         g_free (raw_filename);
593
594         gl_debug (DEBUG_FILE, "END");
595 }
596
597 /*---------------------------------------------------------------------------*/
598 /* PRIVATE.  "Save As" cancel button callback.                               */
599 /*---------------------------------------------------------------------------*/
600 static void
601 save_as_cancel_cb (GtkWidget * widget,
602                    GtkFileSelection * fsel)
603 {
604         gboolean *saved_flag = g_object_get_data (G_OBJECT (fsel), "saved_flag");
605
606         g_return_if_fail (GTK_IS_FILE_SELECTION (fsel));
607
608         *saved_flag = FALSE;
609         gtk_widget_hide (GTK_WIDGET (fsel));
610         gtk_main_quit ();
611 }
612
613 /*---------------------------------------------------------------------------*/
614 /* PRIVATE.  "Save As" destroy callback.                                     */
615 /*---------------------------------------------------------------------------*/
616 static void
617 save_as_destroy_cb (GtkWidget * widget,
618                     gboolean * destroy_flag)
619 {
620         *destroy_flag = TRUE;
621         gtk_main_quit ();
622 }
623
624
625 /*****************************************************************************/
626 /* "Close" menu callback.                                                    */
627 /*****************************************************************************/
628 void
629 gl_file_close (GtkWidget * view)
630 {
631         gint ret;
632         BonoboMDIChild* child;
633
634         gl_debug (DEBUG_FILE, "START");
635
636         g_return_if_fail (view != NULL);
637
638         child = bonobo_mdi_get_child_from_view (view);
639         g_return_if_fail (child != NULL);
640
641         if (g_list_length (bonobo_mdi_child_get_views (child)) > 1)
642         {               
643                 ret = bonobo_mdi_remove_view (BONOBO_MDI (glabels_mdi), view, FALSE);
644                 gl_debug (DEBUG_FILE, "View removed.");
645         }
646         else
647         {
648                 ret = bonobo_mdi_remove_child (BONOBO_MDI (glabels_mdi), child, FALSE);
649                 gl_debug (DEBUG_FILE, "Child removed.");
650         }
651
652         if (ret)
653                 gl_mdi_set_active_window_title (BONOBO_MDI (glabels_mdi));
654
655         if (bonobo_mdi_get_active_child (BONOBO_MDI (glabels_mdi)) == NULL)
656         {
657                 gl_mdi_set_active_window_verbs_sensitivity (BONOBO_MDI (glabels_mdi));
658         }
659
660         gl_debug (DEBUG_FILE, "END");
661 }
662
663 /*****************************************************************************/
664 /* "Close all"                                                               */
665 /*****************************************************************************/
666 gboolean
667 gl_file_close_all (void)
668 {
669         gboolean ret;
670         gl_debug (DEBUG_FILE, "");
671
672         gl_debug (DEBUG_FILE, "START");
673
674         ret = bonobo_mdi_remove_all (BONOBO_MDI (glabels_mdi), FALSE);
675
676         if (bonobo_mdi_get_active_child (BONOBO_MDI (glabels_mdi)) == NULL)
677         {
678                 gl_mdi_set_active_window_verbs_sensitivity (BONOBO_MDI (glabels_mdi));
679         }
680
681         gl_debug (DEBUG_FILE, "END");
682
683         return ret;
684 }
685
686 /*****************************************************************************/
687 /* "Exit" menu callback.                                                     */
688 /*****************************************************************************/
689 void
690 gl_file_exit (void)
691 {
692         gl_debug (DEBUG_FILE, "");
693         
694         if (!gl_file_close_all ())
695                 return;
696
697         gl_debug (DEBUG_FILE, "All files closed.");
698         
699         /* We need to disconnect the signal because mdi "destroy" event
700            is connected to gl_file_exit ( i.e. this function ). */
701         g_signal_handlers_disconnect_by_func (G_OBJECT (glabels_mdi),
702                                               G_CALLBACK (gl_file_exit), NULL);
703         
704         gl_prefs_save_settings ();
705
706         gl_debug (DEBUG_FILE, "Unref glabels_mdi.");
707
708         g_object_unref (G_OBJECT (glabels_mdi));
709
710         gl_debug (DEBUG_FILE, "Unref glabels_mdi: DONE");
711
712         gtk_main_quit ();
713
714         gl_debug (DEBUG_FILE, "END");
715 }