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