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