]> www.fi.muni.cz Git - evince.git/blob - shell/ev-application.c
[shell] Recover previous session when running evince after a crash
[evince.git] / shell / ev-application.c
1 /* this file is part of evince, a gnome document viewer
2  *
3  *  Copyright (C) 2004 Martin Kretzschmar
4  *
5  *  Author:
6  *    Martin Kretzschmar <martink@gnome.org>
7  *
8  * Evince is free software; you can redistribute it and/or modify it
9  * 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  * Evince is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * 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 <stdlib.h>
26 #include <string.h>
27
28 #include <glib.h>
29 #include <glib/gi18n.h>
30 #include <gtk/gtk.h>
31 #ifdef GDK_WINDOWING_X11
32 #include <gdk/gdkx.h>
33 #endif
34
35 #include "totem-scrsaver.h"
36 #include "eggsmclient.h"
37
38 #include "ev-application.h"
39 #include "ev-document-factory.h"
40 #include "ev-file-helpers.h"
41 #include "ev-metadata-manager.h"
42 #include "ev-utils.h"
43 #include "ev-stock-icons.h"
44
45 #ifdef ENABLE_DBUS
46 #include "ev-media-player-keys.h"
47 #endif /* ENABLE_DBUS */
48
49 #ifdef ENABLE_DBUS
50 #include <dbus/dbus-glib-bindings.h>
51 #include "ev-application-service.h"
52 #endif
53
54 static void ev_application_save_print_settings (EvApplication *application);
55
56 struct _EvApplication {
57         GObject base_instance;
58
59         gchar *dot_dir;
60         gchar *accel_map_file;
61         gchar *toolbars_file;
62         gchar *crashed_file;
63         guint  crashed_idle;
64
65         EggToolbarsModel *toolbars_model;
66
67         TotemScrsaver *scr_saver;
68
69         EggSMClient *smclient;
70
71         gchar *last_chooser_uri;
72
73 #ifdef ENABLE_DBUS
74         EvMediaPlayerKeys *keys;
75 #endif /* ENABLE_DBUS */
76
77         GtkPrintSettings *print_settings;
78         GtkPageSetup     *page_setup;
79         GKeyFile         *print_settings_file;
80 };
81
82 struct _EvApplicationClass {
83         GObjectClass base_class;
84 };
85
86 static EvApplication *instance;
87
88 G_DEFINE_TYPE (EvApplication, ev_application, G_TYPE_OBJECT);
89
90 #define APPLICATION_SERVICE_NAME "org.gnome.evince.ApplicationService"
91
92 #define EV_PRINT_SETTINGS_FILE "print-settings"
93 #define EV_PRINT_SETTINGS_GROUP "Print Settings"
94 #define EV_PAGE_SETUP_GROUP "Page Setup"
95
96 #ifdef ENABLE_DBUS
97 gboolean
98 ev_application_register_service (EvApplication *application)
99 {
100         static DBusGConnection *connection = NULL;
101         DBusGProxy *driver_proxy;
102         GError *err = NULL;
103         guint request_name_result;
104
105         if (connection) {
106                 g_warning ("Service already registered.");
107                 return FALSE;
108         }
109         
110         connection = dbus_g_bus_get (DBUS_BUS_STARTER, &err);
111         if (connection == NULL) {
112                 g_warning ("Service registration failed.");
113                 g_error_free (err);
114
115                 return FALSE;
116         }
117
118         driver_proxy = dbus_g_proxy_new_for_name (connection,
119                                                   DBUS_SERVICE_DBUS,
120                                                   DBUS_PATH_DBUS,
121                                                   DBUS_INTERFACE_DBUS);
122
123         if (!org_freedesktop_DBus_request_name (driver_proxy,
124                                                 APPLICATION_SERVICE_NAME,
125                                                 DBUS_NAME_FLAG_DO_NOT_QUEUE,
126                                                 &request_name_result, &err)) {
127                 g_warning ("Service registration failed.");
128                 g_clear_error (&err);
129         }
130
131         g_object_unref (driver_proxy);
132         
133         if (request_name_result == DBUS_REQUEST_NAME_REPLY_EXISTS) {
134                 return FALSE;
135         }
136
137         dbus_g_object_type_install_info (EV_TYPE_APPLICATION,
138                                          &dbus_glib_ev_application_object_info);
139         dbus_g_connection_register_g_object (connection,
140                                              "/org/gnome/evince/Evince",
141                                              G_OBJECT (application));
142         
143         application->scr_saver = totem_scrsaver_new (connection);
144
145         ev_metadata_manager_init ();
146
147         return TRUE;
148 }
149 #endif /* ENABLE_DBUS */
150
151 /**
152  * ev_application_get_instance:
153  *
154  * Checks for #EvApplication instance, if it doesn't exist it does create it.
155  *
156  * Returns: an instance of the #EvApplication data.
157  */
158 EvApplication *
159 ev_application_get_instance (void)
160 {
161         if (!instance) {
162                 instance = EV_APPLICATION (g_object_new (EV_TYPE_APPLICATION, NULL));
163         }
164
165         return instance;
166 }
167
168 /* Session */
169 static void
170 save_session (EvApplication *application,
171               GList         *windows_list,
172               GKeyFile      *state_file)
173 {
174         GList *l;
175         gint i;
176         const gchar **uri_list;
177         const gchar *empty = "empty-window";
178
179         uri_list = g_new (const gchar *, g_list_length (windows_list));
180         for (l = windows_list, i = 0; l != NULL; l = g_list_next (l), i++) {
181                 EvWindow *window = EV_WINDOW (l->data);
182
183                 if (ev_window_is_empty (window))
184                         uri_list[i] = empty;
185                 else
186                         uri_list[i] = ev_window_get_uri (window);
187         }
188         g_key_file_set_string_list (state_file,
189                                     "Evince",
190                                     "documents",
191                                     (const char **)uri_list,
192                                     i);
193         g_free (uri_list);
194 }
195
196 static void
197 ev_application_save_session_crashed (EvApplication *application)
198 {
199         GList *windows;
200
201         windows = ev_application_get_windows (application);
202         if (windows) {
203                 GKeyFile *crashed_file;
204                 gchar    *data;
205                 gssize    data_length;
206                 GError   *error = NULL;
207
208                 crashed_file = g_key_file_new ();
209                 save_session (application, windows, crashed_file);
210
211                 data = g_key_file_to_data (crashed_file, (gsize *)&data_length, NULL);
212                 g_file_set_contents (application->crashed_file, data, data_length, &error);
213                 if (error) {
214                         g_warning ("%s", error->message);
215                         g_error_free (error);
216                 }
217                 g_free (data);
218                 g_key_file_free (crashed_file);
219         } else if (g_file_test (application->crashed_file, G_FILE_TEST_IS_REGULAR)) {
220                 GFile *file;
221
222                 file = g_file_new_for_path (application->crashed_file);
223                 g_file_delete (file, NULL, NULL);
224                 g_object_unref (file);
225         }
226 }
227
228 static gboolean
229 save_session_crashed_in_idle_cb (EvApplication *application)
230 {
231         ev_application_save_session_crashed (application);
232         application->crashed_idle = 0;
233
234         return FALSE;
235 }
236
237 static void
238 save_session_crashed_in_idle (EvApplication *application)
239 {
240         if (application->crashed_idle > 0)
241                 g_source_remove (application->crashed_idle);
242         application->crashed_idle =
243                 g_idle_add ((GSourceFunc)save_session_crashed_in_idle_cb,
244                             application);
245 }
246
247 static gboolean
248 ev_application_run_crash_recovery_dialog (EvApplication *application)
249 {
250         GtkWidget *dialog;
251         gint       response;
252
253         dialog = gtk_message_dialog_new (NULL,
254                                          GTK_DIALOG_MODAL,
255                                          GTK_MESSAGE_WARNING,
256                                          GTK_BUTTONS_NONE,
257                                          _("Recover previous documents?"));
258         gtk_message_dialog_format_secondary_text (
259                 GTK_MESSAGE_DIALOG (dialog),
260                 _("Evince appears to have exited unexpectedly the last time "
261                   "it was run. You can recover the opened documents."));
262
263         gtk_dialog_add_button (GTK_DIALOG (dialog),
264                                _("_Don't Recover"),
265                                GTK_RESPONSE_CANCEL);
266         gtk_dialog_add_button (GTK_DIALOG (dialog),
267                                _("_Recover"),
268                                GTK_RESPONSE_ACCEPT);
269
270         gtk_window_set_title (GTK_WINDOW (dialog), _("Crash Recovery"));
271         gtk_window_set_icon_name (GTK_WINDOW (dialog), "evince");
272         gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
273         gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), FALSE);
274         gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
275
276         response = gtk_dialog_run (GTK_DIALOG (dialog));
277         gtk_widget_destroy (dialog);
278
279         return response == GTK_RESPONSE_ACCEPT;
280 }
281
282 gboolean
283 ev_application_load_session (EvApplication *application)
284 {
285         GKeyFile *state_file;
286         gchar   **uri_list;
287
288         if (egg_sm_client_is_resumed (application->smclient)) {
289                 state_file = egg_sm_client_get_state_file (application->smclient);
290                 if (!state_file)
291                         return FALSE;
292         } else if (g_file_test (application->crashed_file, G_FILE_TEST_IS_REGULAR)) {
293                 if (ev_application_run_crash_recovery_dialog (application)) {
294                         state_file = g_key_file_new ();
295                         g_key_file_load_from_file (state_file,
296                                                    application->crashed_file,
297                                                    G_KEY_FILE_NONE,
298                                                    NULL);
299                 } else {
300                         return FALSE;
301                 }
302         } else {
303                 return FALSE;
304         }
305
306         uri_list = g_key_file_get_string_list (state_file,
307                                                "Evince",
308                                                "documents",
309                                                NULL, NULL);
310         if (uri_list) {
311                 gint i;
312
313                 for (i = 0; uri_list[i]; i++) {
314                         if (g_ascii_strcasecmp (uri_list[i], "empty-window") == 0)
315                                 ev_application_open_window (application, NULL, GDK_CURRENT_TIME, NULL);
316                         else
317                                 ev_application_open_uri (application, uri_list[i], NULL, GDK_CURRENT_TIME, NULL);
318                 }
319                 g_strfreev (uri_list);
320         }
321         g_key_file_free (state_file);
322
323         return TRUE;
324 }
325
326 static void
327 smclient_save_state_cb (EggSMClient   *client,
328                         GKeyFile      *state_file,
329                         EvApplication *application)
330 {
331         GList *windows;
332
333         windows = ev_application_get_windows (application);
334         if (windows) {
335                 save_session (application, windows, state_file);
336                 g_list_free (windows);
337         }
338 }
339
340 static void
341 smclient_quit_cb (EggSMClient   *client,
342                   EvApplication *application)
343 {
344         ev_application_shutdown (application);
345 }
346
347 static void
348 ev_application_init_session (EvApplication *application)
349 {
350         application->crashed_file = g_build_filename (application->dot_dir,
351                                                       "evince-crashed", NULL);
352
353         application->smclient = egg_sm_client_get ();
354         g_signal_connect (application->smclient, "save_state",
355                           G_CALLBACK (smclient_save_state_cb),
356                           application);
357         g_signal_connect (application->smclient, "quit",
358                           G_CALLBACK (smclient_quit_cb),
359                           application);
360 }
361
362 /**
363  * ev_display_open_if_needed:
364  * @name: the name of the display to be open if it's needed.
365  *
366  * Search among all the open displays if any of them have the same name as the
367  * passed name. If the display isn't found it tries the open it.
368  *
369  * Returns: a #GdkDisplay of the display with the passed name.
370  */
371 static GdkDisplay *
372 ev_display_open_if_needed (const gchar *name)
373 {
374         GSList     *displays;
375         GSList     *l;
376         GdkDisplay *display = NULL;
377
378         displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
379
380         for (l = displays; l != NULL; l = l->next) {
381                 const gchar *display_name = gdk_display_get_name ((GdkDisplay *) l->data);
382
383                 if (g_ascii_strcasecmp (display_name, name) == 0) {
384                         display = l->data;
385                         break;
386                 }
387         }
388
389         g_slist_free (displays);
390
391         return display != NULL ? display : gdk_display_open (name);
392 }
393
394 /**
395  * get_screen_from_args:
396  * @args: a #GHashTable with data passed to the application.
397  *
398  * Looks for the screen in the display available in the hash table passed to the
399  * application. If the display isn't opened, it's opened and the #GdkScreen
400  * assigned to the screen in that display returned.
401  *
402  * Returns: the #GdkScreen assigned to the screen on the display indicated by
403  *          the data on the #GHashTable.
404  */
405 static GdkScreen *
406 get_screen_from_args (GHashTable *args)
407 {
408         GValue     *value = NULL;
409         GdkDisplay *display = NULL;
410         GdkScreen  *screen = NULL;
411
412         g_assert (args != NULL);
413         
414         value = g_hash_table_lookup (args, "display");
415         if (value) {
416                 const gchar *display_name;
417                 
418                 display_name = g_value_get_string (value);
419                 display = ev_display_open_if_needed (display_name);
420         }
421         
422         value = g_hash_table_lookup (args, "screen");
423         if (value) {
424                 gint screen_number;
425                 
426                 screen_number = g_value_get_int (value);
427                 screen = gdk_display_get_screen (display, screen_number);
428         }
429
430         return screen;
431 }
432
433 /**
434  * get_window_run_mode_from_args:
435  * @args: a #GHashTable with data passed to the application.
436  *
437  * It does look if the mode option has been passed from command line, using it
438  * as the window run mode, otherwise the run mode will be the normal mode.
439  *
440  * Returns: The window run mode passed from command line or
441  *          EV_WINDOW_MODE_NORMAL in other case.
442  */
443 static EvWindowRunMode
444 get_window_run_mode_from_args (GHashTable *args)
445 {
446         EvWindowRunMode  mode = EV_WINDOW_MODE_NORMAL;
447         GValue          *value = NULL;
448
449         g_assert (args != NULL);
450
451         value = g_hash_table_lookup (args, "mode");
452         if (value) {
453                 mode = g_value_get_uint (value);
454         }
455
456         return mode;
457 }
458
459 /**
460  * get_destination_from_args:
461  * @args: a #GHashTable with data passed to the application.
462  *
463  * It does look for the page-label argument parsed from the command line and
464  * if it does exist, it returns an #EvLinkDest.
465  *
466  * Returns: An #EvLinkDest to page-label if it has been passed from the command
467  *          line, NULL in other case.
468  */
469 static EvLinkDest *
470 get_destination_from_args (GHashTable *args)
471 {
472         EvLinkDest *dest = NULL;
473         GValue     *value = NULL;
474         
475         g_assert (args != NULL);
476         
477         value = g_hash_table_lookup (args, "page-label");
478         if (value) {
479                 const gchar *page_label;
480
481                 page_label = g_value_get_string (value);
482                 dest = ev_link_dest_new_page_label (page_label);
483         }
484
485         return dest;
486 }
487
488 static const gchar *
489 get_find_string_from_args (GHashTable *args)
490 {
491         GValue *value = NULL;
492
493         g_assert (args != NULL);
494
495         value = g_hash_table_lookup (args, "find-string");
496         
497         return value ? g_value_get_string (value) : NULL;
498 }
499
500 /**
501  * ev_application_open_window:
502  * @application: The instance of the application.
503  * @args: A #GHashTable with the arguments data.
504  * @timestamp: Current time value.
505  * @error: The #GError facility.
506  * 
507  * Creates a new window and if the args are available, it's not NULL, it gets
508  * the screen from them and assigns the just created window to it. At last it
509  * does show it.
510  *
511  * Returns: %TRUE.
512  */
513 gboolean
514 ev_application_open_window (EvApplication  *application,
515                             GHashTable     *args,
516                             guint32         timestamp,
517                             GError        **error)
518 {
519         GtkWidget *new_window = ev_window_new ();
520         GdkScreen *screen = NULL;
521
522         if (args) {
523                 screen = get_screen_from_args (args);
524         }
525         
526         if (screen) {
527                 ev_stock_icons_set_screen (screen);
528                 gtk_window_set_screen (GTK_WINDOW (new_window), screen);
529         }
530
531         ev_application_save_session_crashed (application);
532         g_signal_connect_swapped (new_window, "destroy",
533                                   G_CALLBACK (save_session_crashed_in_idle),
534                                   application);
535
536         if (!GTK_WIDGET_REALIZED (new_window))
537                 gtk_widget_realize (new_window);
538         
539 #ifdef GDK_WINDOWING_X11
540         if (timestamp <= 0)
541                 timestamp = gdk_x11_get_server_time (GTK_WIDGET (new_window)->window);
542         gdk_x11_window_set_user_time (GTK_WIDGET (new_window)->window, timestamp);
543         
544         gtk_window_present (GTK_WINDOW (new_window));
545 #else
546         gtk_window_present_with_time (GTK_WINDOW (new_window), timestamp);
547 #endif /* GDK_WINDOWING_X11 */
548
549         return TRUE;
550 }
551
552 /**
553  * ev_application_get_empty_window:
554  * @application: The instance of the application.
555  * @screen: The screen where the empty window will be search.
556  *
557  * It does look if there is any empty window in the indicated screen.
558  *
559  * Returns: The first empty #EvWindow in the passed #GdkScreen or NULL in other
560  *          case.
561  */
562 static EvWindow *
563 ev_application_get_empty_window (EvApplication *application,
564                                  GdkScreen     *screen)
565 {
566         EvWindow *empty_window = NULL;
567         GList *windows = ev_application_get_windows (application);
568         GList *l;
569
570         for (l = windows; l != NULL; l = l->next) {
571                 EvWindow *window = EV_WINDOW (l->data);
572
573                 if (ev_window_is_empty (window) &&
574                     gtk_window_get_screen (GTK_WINDOW (window)) == screen) {
575                         empty_window = window;
576                         break;
577                 }
578         }
579
580         g_list_free (windows);
581         
582         return empty_window;
583 }
584
585 /**
586  * ev_application_get_uri_window:
587  * @application: The instance of the application.
588  * @uri: The uri to be opened.
589  *
590  * It looks in the list of the windows for the one with the document represented
591  * by the passed uri on it. If the window is empty or the document isn't present
592  * on any window, it will return NULL.
593  *
594  * Returns: The #EvWindow where the document represented by the passed uri is
595  *          shown, NULL in other case.
596  */
597 static EvWindow *
598 ev_application_get_uri_window (EvApplication *application, const char *uri)
599 {
600         EvWindow *uri_window = NULL;
601         GList *windows = gtk_window_list_toplevels ();
602         GList *l;
603
604         g_return_val_if_fail (uri != NULL, NULL);
605
606         for (l = windows; l != NULL; l = l->next) {
607                 if (EV_IS_WINDOW (l->data)) {
608                         EvWindow *window = EV_WINDOW (l->data);
609                         const char *window_uri = ev_window_get_uri (window);
610
611                         if (window_uri && strcmp (window_uri, uri) == 0 && !ev_window_is_empty (window)) {
612                                 uri_window = window;
613                                 break;
614                         }
615                 }
616         }
617
618         g_list_free (windows);
619         
620         return uri_window;
621 }
622
623 /**
624  * ev_application_open_uri_at_dest:
625  * @application: The instance of the application.
626  * @uri: The uri to be opened.
627  * @screen: Thee screen where the link will be shown.
628  * @dest: The #EvLinkDest of the document.
629  * @mode: The run mode of the window.
630  * @timestamp: Current time value.
631  */
632 void
633 ev_application_open_uri_at_dest (EvApplication  *application,
634                                  const char     *uri,
635                                  GdkScreen      *screen,
636                                  EvLinkDest     *dest,
637                                  EvWindowRunMode mode,
638                                  const gchar    *search_string,
639                                  guint           timestamp)
640 {
641         EvWindow *new_window;
642
643         g_return_if_fail (uri != NULL);
644         
645         new_window = ev_application_get_uri_window (application, uri);
646         
647         if (new_window == NULL) {
648                 new_window = ev_application_get_empty_window (application, screen);
649         }
650
651         if (new_window == NULL) {
652                 new_window = EV_WINDOW (ev_window_new ());
653         }
654
655         if (screen) {
656                 ev_stock_icons_set_screen (screen);
657                 gtk_window_set_screen (GTK_WINDOW (new_window), screen);
658         }
659
660         /* We need to load uri before showing the window, so
661            we can restore window size without flickering */     
662         ev_window_open_uri (new_window, uri, dest, mode, search_string);
663
664         ev_application_save_session_crashed (application);
665         g_signal_connect_swapped (new_window, "destroy",
666                                   G_CALLBACK (save_session_crashed_in_idle),
667                                   application);
668
669         if (!GTK_WIDGET_REALIZED (GTK_WIDGET (new_window)))
670                 gtk_widget_realize (GTK_WIDGET (new_window));
671
672 #ifdef GDK_WINDOWING_X11
673         if (timestamp <= 0)
674                 timestamp = gdk_x11_get_server_time (GTK_WIDGET (new_window)->window);
675         gdk_x11_window_set_user_time (GTK_WIDGET (new_window)->window, timestamp);
676
677         ev_document_fc_mutex_lock ();
678         gtk_window_present (GTK_WINDOW (new_window));
679         ev_document_fc_mutex_unlock ();
680 #else
681         ev_document_fc_mutex_lock ();
682         gtk_window_present_with_time (GTK_WINDOW (new_window), timestamp);
683         ev_document_fc_mutex_unlock ();
684 #endif /* GDK_WINDOWING_X11 */
685 }
686
687 /**
688  * ev_application_open_uri:
689  * @application: The instance of the application.
690  * @uri: The uri to be opened
691  * @args: A #GHashTable with the arguments data.
692  * @timestamp: Current time value.
693  * @error: The #GError facility.
694  */
695 gboolean
696 ev_application_open_uri (EvApplication  *application,
697                          const char     *uri,
698                          GHashTable     *args,
699                          guint           timestamp,
700                          GError        **error)
701 {
702         EvLinkDest      *dest = NULL;
703         EvWindowRunMode  mode = EV_WINDOW_MODE_NORMAL;
704         const gchar     *search_string = NULL;
705         GdkScreen       *screen = NULL;
706
707         if (args) {
708                 screen = get_screen_from_args (args);
709                 dest = get_destination_from_args (args);
710                 mode = get_window_run_mode_from_args (args);
711                 search_string = get_find_string_from_args (args);
712         }
713         
714         ev_application_open_uri_at_dest (application, uri, screen,
715                                          dest, mode, search_string,
716                                          timestamp);
717
718         if (dest)
719                 g_object_unref (dest);
720
721         return TRUE;
722 }
723
724 void
725 ev_application_open_uri_list (EvApplication *application,
726                               GSList        *uri_list,
727                               GdkScreen     *screen,
728                               guint          timestamp)
729 {
730         GSList *l;
731
732         for (l = uri_list; l != NULL; l = l->next) {
733                 ev_application_open_uri_at_dest (application, (char *)l->data,
734                                                  screen, NULL, 0, NULL,
735                                                  timestamp);
736         }
737 }
738
739 void
740 ev_application_shutdown (EvApplication *application)
741 {
742         if (application->crashed_file) {
743                 ev_application_save_session_crashed (application);
744                 g_free (application->crashed_file);
745                 application->crashed_file = NULL;
746         }
747
748         if (application->accel_map_file) {
749                 gtk_accel_map_save (application->accel_map_file);
750                 g_free (application->accel_map_file);
751                 application->accel_map_file = NULL;
752         }
753         
754         if (application->toolbars_model) {
755                 g_object_unref (application->toolbars_model);
756                 g_free (application->toolbars_file);
757                 application->toolbars_model = NULL;
758                 application->toolbars_file = NULL;
759         }
760
761         ev_application_save_print_settings (application);
762         
763         if (application->print_settings_file) {
764                 g_key_file_free (application->print_settings_file);
765                 application->print_settings_file = NULL;
766         }
767
768         if (application->print_settings) {
769                 g_object_unref (application->print_settings);
770                 application->print_settings = NULL;
771         }
772
773         if (application->page_setup) {
774                 g_object_unref (application->page_setup);
775                 application->page_setup = NULL;
776         }
777
778 #ifdef ENABLE_DBUS
779         if (application->keys) {
780                 g_object_unref (application->keys);
781                 application->keys = NULL;
782         }
783 #endif /* ENABLE_DBUS */
784         
785         ev_metadata_manager_shutdown ();
786
787         g_free (application->dot_dir);
788         application->dot_dir = NULL;
789         g_free (application->last_chooser_uri);
790         application->last_chooser_uri = NULL;
791
792         g_object_unref (application);
793         instance = NULL;
794         
795         gtk_main_quit ();
796 }
797
798 static void
799 ev_application_class_init (EvApplicationClass *ev_application_class)
800 {
801 }
802
803 static void
804 ev_application_init (EvApplication *ev_application)
805 {
806         gint i;
807         const gchar *home_dir;
808
809         ev_application->dot_dir = g_build_filename (g_get_home_dir (),
810                                                     ".gnome2",
811                                                     "evince",
812                                                     NULL);
813
814         /* FIXME: why make this fatal? */
815         if (!ev_dir_ensure_exists (ev_application->dot_dir, 0700))
816                 exit (1);
817
818         ev_application_init_session (ev_application);
819
820         home_dir = g_get_home_dir ();
821         if (home_dir) {
822                 ev_application->accel_map_file = g_build_filename (home_dir,
823                                                                    ".gnome2",
824                                                                    "accels",
825                                                                    "evince",
826                                                                    NULL);
827                 gtk_accel_map_load (ev_application->accel_map_file);
828         }
829         
830         ev_application->toolbars_model = egg_toolbars_model_new ();
831
832         ev_application->toolbars_file = g_build_filename
833                         (ev_application->dot_dir, "evince_toolbar.xml", NULL);
834
835         egg_toolbars_model_load_names (ev_application->toolbars_model,
836                                        DATADIR "/evince-toolbar.xml");
837
838         if (!egg_toolbars_model_load_toolbars (ev_application->toolbars_model,
839                                                ev_application->toolbars_file)) {
840                 egg_toolbars_model_load_toolbars (ev_application->toolbars_model,
841                                                   DATADIR"/evince-toolbar.xml");
842         }
843
844         /* Open item doesn't exist anymore,
845          * convert it to OpenRecent for compatibility
846          */
847         for (i = 0; i < egg_toolbars_model_n_items (ev_application->toolbars_model, 0); i++) {
848                 const gchar *item;
849                 
850                 item = egg_toolbars_model_item_nth (ev_application->toolbars_model, 0, i);
851                 if (g_ascii_strcasecmp (item, "FileOpen") == 0) {
852                         egg_toolbars_model_remove_item (ev_application->toolbars_model, 0, i);
853                         egg_toolbars_model_add_item (ev_application->toolbars_model, 0, i,
854                                                      "FileOpenRecent");
855                         ev_application_save_toolbars_model (ev_application);
856                         break;
857                 }
858         }
859
860         egg_toolbars_model_set_flags (ev_application->toolbars_model, 0,
861                                       EGG_TB_MODEL_NOT_REMOVABLE);
862
863 #ifdef ENABLE_DBUS
864         ev_application->keys = ev_media_player_keys_new ();
865 #endif /* ENABLE_DBUS */
866 }
867
868 /**
869  * ev_application_get_windows:
870  * @application: The instance of the application.
871  *
872  * It creates a list of the top level windows.
873  *
874  * Returns: A #GList of the top level windows.
875  */
876 GList *
877 ev_application_get_windows (EvApplication *application)
878 {
879         GList *l, *toplevels;
880         GList *windows = NULL;
881
882         toplevels = gtk_window_list_toplevels ();
883
884         for (l = toplevels; l != NULL; l = l->next) {
885                 if (EV_IS_WINDOW (l->data)) {
886                         windows = g_list_append (windows, l->data);
887                 }
888         }
889
890         g_list_free (toplevels);
891
892         return windows;
893 }
894
895 /**
896  * ev_application_get_media_keys:
897  * @application: The instance of the application.
898  *
899  * It gives you access to the media player keys handler object.
900  *
901  * Returns: A #EvMediaPlayerKeys.
902  */
903 GObject *
904 ev_application_get_media_keys (EvApplication *application)
905 {
906 #ifdef ENABLE_DBUS
907         return G_OBJECT (application->keys);
908 #else
909         return NULL;
910 #endif /* ENABLE_DBUS */
911 }
912
913 EggToolbarsModel *
914 ev_application_get_toolbars_model (EvApplication *application)
915 {
916         return application->toolbars_model;
917 }
918
919 void
920 ev_application_save_toolbars_model (EvApplication *application)
921 {
922         egg_toolbars_model_save_toolbars (application->toolbars_model,
923                                           application->toolbars_file, "1.0");
924 }
925
926 void
927 ev_application_set_chooser_uri (EvApplication *application, const gchar *uri)
928 {
929         g_free (application->last_chooser_uri);
930         application->last_chooser_uri = g_strdup (uri);
931 }
932
933 const gchar *
934 ev_application_get_chooser_uri (EvApplication *application)
935 {
936         return application->last_chooser_uri;
937 }
938
939 void
940 ev_application_screensaver_enable (EvApplication *application)
941 {
942         if (application->scr_saver)
943                 totem_scrsaver_enable (application->scr_saver); 
944 }
945
946 void
947 ev_application_screensaver_disable (EvApplication *application)
948 {
949         if (application->scr_saver)
950                 totem_scrsaver_disable (application->scr_saver);        
951 }
952
953 static GKeyFile *
954 ev_application_get_print_settings_file (EvApplication *application)
955 {
956         gchar *filename;
957         
958         if (application->print_settings_file)
959                 return application->print_settings_file;
960
961         application->print_settings_file = g_key_file_new ();
962         
963         filename = g_build_filename (ev_application_get_dot_dir (application), EV_PRINT_SETTINGS_FILE, NULL);
964         if (g_file_test (filename, G_FILE_TEST_IS_REGULAR)) {
965                 GError *error = NULL;
966
967                 g_key_file_load_from_file (application->print_settings_file,
968                                            filename,
969                                            G_KEY_FILE_KEEP_COMMENTS |
970                                            G_KEY_FILE_KEEP_TRANSLATIONS,
971                                            &error);
972                 if (error) {
973                         g_warning ("%s", error->message);
974                         g_error_free (error);
975                 }
976         }
977         g_free (filename);
978
979         return application->print_settings_file;
980 }
981
982 static void
983 ev_application_save_print_settings (EvApplication *application)
984 {
985         GKeyFile *key_file;
986         gchar    *filename;
987         gchar    *data;
988         gssize    data_length;
989         GError   *error = NULL;
990
991         if (!application->print_settings && !application->page_setup)
992                 return;
993         
994         key_file = ev_application_get_print_settings_file (application);
995         if (application->print_settings)
996                 gtk_print_settings_to_key_file (application->print_settings,
997                                                 key_file,
998                                                 EV_PRINT_SETTINGS_GROUP);
999         if (application->page_setup)
1000                 gtk_page_setup_to_key_file (application->page_setup,
1001                                             key_file,
1002                                             EV_PAGE_SETUP_GROUP);
1003         
1004         filename = g_build_filename (ev_application_get_dot_dir (application), EV_PRINT_SETTINGS_FILE, NULL);
1005         data = g_key_file_to_data (key_file, (gsize *)&data_length, NULL);
1006         g_file_set_contents (filename, data, data_length, &error);
1007         if (error) {
1008                 g_warning ("%s", error->message);
1009                 g_error_free (error);
1010         }
1011         g_free (data);
1012         g_free (filename);
1013 }
1014
1015 GtkPrintSettings *
1016 ev_application_get_print_settings (EvApplication *application)
1017 {
1018         GKeyFile         *key_file;
1019         GtkPrintSettings *print_settings;
1020         
1021         if (application->print_settings)
1022                 return application->print_settings;
1023
1024         key_file = ev_application_get_print_settings_file (application);
1025         print_settings = g_key_file_has_group (key_file, EV_PRINT_SETTINGS_GROUP) ? 
1026                 gtk_print_settings_new_from_key_file (key_file, EV_PRINT_SETTINGS_GROUP, NULL) :
1027                 gtk_print_settings_new ();
1028
1029         application->print_settings = print_settings ? print_settings : gtk_print_settings_new ();
1030
1031         return application->print_settings;
1032 }
1033
1034 void
1035 ev_application_set_print_settings (EvApplication    *application,
1036                                    GtkPrintSettings *settings)
1037 {
1038         GKeyFile *key_file;
1039         
1040         g_return_if_fail (GTK_IS_PRINT_SETTINGS (settings));
1041         
1042         if (settings == application->print_settings)
1043                 return;
1044
1045         key_file = ev_application_get_print_settings_file (application);
1046         
1047         if (application->print_settings)
1048                 g_object_unref (application->print_settings);
1049         
1050         application->print_settings = g_object_ref (settings);
1051         gtk_print_settings_to_key_file (settings, key_file, EV_PRINT_SETTINGS_GROUP);
1052 }
1053
1054 GtkPageSetup *
1055 ev_application_get_page_setup (EvApplication *application)
1056 {
1057         GKeyFile     *key_file;
1058         GtkPageSetup *page_setup;
1059         
1060         if (application->page_setup)
1061                 return application->page_setup;
1062
1063         key_file = ev_application_get_print_settings_file (application);
1064         page_setup = g_key_file_has_group (key_file, EV_PAGE_SETUP_GROUP) ? 
1065                 gtk_page_setup_new_from_key_file (key_file, EV_PAGE_SETUP_GROUP, NULL) :
1066                 gtk_page_setup_new ();
1067
1068         application->page_setup = page_setup ? page_setup : gtk_page_setup_new ();
1069
1070         return application->page_setup;
1071 }
1072
1073 void
1074 ev_application_set_page_setup (EvApplication *application,
1075                                GtkPageSetup  *page_setup)
1076 {
1077         GKeyFile *key_file;
1078         
1079         g_return_if_fail (GTK_IS_PAGE_SETUP (page_setup));
1080         
1081         if (page_setup == application->page_setup)
1082                 return;
1083
1084         key_file = ev_application_get_print_settings_file (application);
1085         
1086         if (application->page_setup)
1087                 g_object_unref (application->page_setup);
1088         
1089         application->page_setup = g_object_ref (page_setup);
1090         gtk_page_setup_to_key_file (page_setup, key_file, EV_PAGE_SETUP_GROUP);
1091 }
1092
1093 const gchar *
1094 ev_application_get_dot_dir (EvApplication   *application)
1095 {
1096         return application->dot_dir;
1097 }