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