]> www.fi.muni.cz Git - evince.git/blob - shell/ev-application.c
Move load/save print settings code from EvApplication to EvWindow
[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
24 #include <config.h>
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 static gboolean ev_application_open_uri (EvApplication  *application,
54                                          const char     *uri,
55                                          GHashTable     *args,
56                                          guint           timestamp,
57                                          GError        **error);
58 #include "ev-application-service.h"
59 #endif
60
61 struct _EvApplication {
62         GObject base_instance;
63
64         gchar *uri;
65
66         gchar *dot_dir;
67         gchar *data_dir;
68         gchar *accel_map_file;
69         gchar *toolbars_file;
70
71 #ifdef ENABLE_DBUS
72         DBusGConnection *connection;
73         EvMediaPlayerKeys *keys;
74 #endif
75
76         EggToolbarsModel *toolbars_model;
77
78         TotemScrsaver *scr_saver;
79
80 #ifdef WITH_SMCLIENT
81         EggSMClient *smclient;
82 #endif
83
84         gchar *filechooser_open_uri;
85         gchar *filechooser_save_uri;
86 };
87
88 struct _EvApplicationClass {
89         GObjectClass base_class;
90 };
91
92 static EvApplication *instance;
93
94 G_DEFINE_TYPE (EvApplication, ev_application, G_TYPE_OBJECT);
95
96 #ifdef ENABLE_DBUS
97 #define APPLICATION_DBUS_OBJECT_PATH "/org/gnome/evince/Evince"
98 #define APPLICATION_DBUS_INTERFACE   "org.gnome.evince.Application"
99 #endif
100
101 /**
102  * ev_application_get_instance:
103  *
104  * Checks for #EvApplication instance, if it doesn't exist it does create it.
105  *
106  * Returns: an instance of the #EvApplication data.
107  */
108 EvApplication *
109 ev_application_get_instance (void)
110 {
111         if (!instance) {
112                 instance = EV_APPLICATION (g_object_new (EV_TYPE_APPLICATION, NULL));
113         }
114
115         return instance;
116 }
117
118 /* Session */
119 gboolean
120 ev_application_load_session (EvApplication *application)
121 {
122         GKeyFile *state_file;
123         gchar    *uri;
124
125 #ifdef WITH_SMCLIENT
126         if (egg_sm_client_is_resumed (application->smclient)) {
127                 state_file = egg_sm_client_get_state_file (application->smclient);
128                 if (!state_file)
129                         return FALSE;
130         } else
131 #endif /* WITH_SMCLIENT */
132                 return FALSE;
133
134         uri = g_key_file_get_string (state_file, "Evince", "uri", NULL);
135         if (!uri)
136                 return FALSE;
137
138         ev_application_open_uri_at_dest (application, uri,
139                                          gdk_screen_get_default (),
140                                          NULL, 0, NULL,
141                                          GDK_CURRENT_TIME);
142         g_free (uri);
143         g_key_file_free (state_file);
144
145         return TRUE;
146 }
147
148 #ifdef WITH_SMCLIENT
149
150 static void
151 smclient_save_state_cb (EggSMClient   *client,
152                         GKeyFile      *state_file,
153                         EvApplication *application)
154 {
155         if (!application->uri)
156                 return;
157
158         g_key_file_set_string (state_file, "Evince", "uri", application->uri);
159 }
160
161 static void
162 smclient_quit_cb (EggSMClient   *client,
163                   EvApplication *application)
164 {
165         ev_application_shutdown (application);
166 }
167 #endif /* WITH_SMCLIENT */
168
169 static void
170 ev_application_init_session (EvApplication *application)
171 {
172 #ifdef WITH_SMCLIENT
173         application->smclient = egg_sm_client_get ();
174         g_signal_connect (application->smclient, "save_state",
175                           G_CALLBACK (smclient_save_state_cb),
176                           application);
177         g_signal_connect (application->smclient, "quit",
178                           G_CALLBACK (smclient_quit_cb),
179                           application);
180 #endif
181 }
182
183 /**
184  * ev_display_open_if_needed:
185  * @name: the name of the display to be open if it's needed.
186  *
187  * Search among all the open displays if any of them have the same name as the
188  * passed name. If the display isn't found it tries the open it.
189  *
190  * Returns: a #GdkDisplay of the display with the passed name.
191  */
192 static GdkDisplay *
193 ev_display_open_if_needed (const gchar *name)
194 {
195         GSList     *displays;
196         GSList     *l;
197         GdkDisplay *display = NULL;
198
199         displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
200
201         for (l = displays; l != NULL; l = l->next) {
202                 const gchar *display_name = gdk_display_get_name ((GdkDisplay *) l->data);
203
204                 if (g_ascii_strcasecmp (display_name, name) == 0) {
205                         display = l->data;
206                         break;
207                 }
208         }
209
210         g_slist_free (displays);
211
212         return display != NULL ? display : gdk_display_open (name);
213 }
214
215 /**
216  * get_screen_from_args:
217  * @args: a #GHashTable with data passed to the application.
218  *
219  * Looks for the screen in the display available in the hash table passed to the
220  * application. If the display isn't opened, it's opened and the #GdkScreen
221  * assigned to the screen in that display returned.
222  *
223  * Returns: the #GdkScreen assigned to the screen on the display indicated by
224  *          the data on the #GHashTable.
225  */
226 static GdkScreen *
227 get_screen_from_args (GHashTable *args)
228 {
229         GValue     *value = NULL;
230         GdkDisplay *display = NULL;
231         GdkScreen  *screen = NULL;
232
233         g_assert (args != NULL);
234         
235         value = g_hash_table_lookup (args, "display");
236         if (value) {
237                 const gchar *display_name;
238                 
239                 display_name = g_value_get_string (value);
240                 display = ev_display_open_if_needed (display_name);
241         }
242         
243         value = g_hash_table_lookup (args, "screen");
244         if (value) {
245                 gint screen_number;
246                 
247                 screen_number = g_value_get_int (value);
248                 screen = gdk_display_get_screen (display, screen_number);
249         }
250
251         return screen;
252 }
253
254 /**
255  * get_window_run_mode_from_args:
256  * @args: a #GHashTable with data passed to the application.
257  *
258  * It does look if the mode option has been passed from command line, using it
259  * as the window run mode, otherwise the run mode will be the normal mode.
260  *
261  * Returns: The window run mode passed from command line or
262  *          EV_WINDOW_MODE_NORMAL in other case.
263  */
264 static EvWindowRunMode
265 get_window_run_mode_from_args (GHashTable *args)
266 {
267         EvWindowRunMode  mode = EV_WINDOW_MODE_NORMAL;
268         GValue          *value = NULL;
269
270         g_assert (args != NULL);
271
272         value = g_hash_table_lookup (args, "mode");
273         if (value) {
274                 mode = g_value_get_uint (value);
275         }
276
277         return mode;
278 }
279
280 /**
281  * get_destination_from_args:
282  * @args: a #GHashTable with data passed to the application.
283  *
284  * It does look for the page-label argument parsed from the command line and
285  * if it does exist, it returns an #EvLinkDest.
286  *
287  * Returns: An #EvLinkDest to page-label if it has been passed from the command
288  *          line, NULL in other case.
289  */
290 static EvLinkDest *
291 get_destination_from_args (GHashTable *args)
292 {
293         EvLinkDest *dest = NULL;
294         GValue     *value = NULL;
295         
296         g_assert (args != NULL);
297         
298         value = g_hash_table_lookup (args, "page-label");
299         if (value) {
300                 const gchar *page_label;
301
302                 page_label = g_value_get_string (value);
303                 dest = ev_link_dest_new_page_label (page_label);
304         }
305
306         return dest;
307 }
308
309 static const gchar *
310 get_find_string_from_args (GHashTable *args)
311 {
312         GValue *value = NULL;
313
314         g_assert (args != NULL);
315
316         value = g_hash_table_lookup (args, "find-string");
317         
318         return value ? g_value_get_string (value) : NULL;
319 }
320
321 static void
322 value_free (GValue *value)
323 {
324         g_value_unset (value);
325         g_free (value);
326 }
327
328 static GHashTable *
329 build_args (GdkScreen      *screen,
330             EvLinkDest     *dest,
331             EvWindowRunMode mode,
332             const gchar    *search_string)
333 {
334         GHashTable  *args;
335         GValue      *value;
336         GdkDisplay  *display;
337         const gchar *display_name;
338         gint         screen_number;
339
340         args = g_hash_table_new_full (g_str_hash,
341                                       g_str_equal,
342                                       (GDestroyNotify)g_free,
343                                       (GDestroyNotify)value_free);
344
345         /* Display */
346         display = gdk_screen_get_display (screen);
347         display_name = gdk_display_get_name (display);
348         value = g_new0 (GValue, 1);
349         g_value_init (value, G_TYPE_STRING);
350         g_value_set_string (value, display_name);
351         g_hash_table_insert (args, g_strdup ("display"), value);
352
353         /* Screen */
354         screen_number = gdk_screen_get_number (screen);
355         value = g_new0 (GValue, 1);
356         g_value_init (value, G_TYPE_INT);
357         g_value_set_int (value, screen_number);
358         g_hash_table_insert (args, g_strdup ("screen"), value);
359
360         /* Page label */
361         if (dest) {
362                 value = g_new0 (GValue, 1);
363                 g_value_init (value, G_TYPE_STRING);
364                 g_value_set_string (value, ev_link_dest_get_page_label (dest));
365
366                 g_hash_table_insert (args, g_strdup ("page-label"), value);
367         }
368
369         /* Find string */
370         if (search_string) {
371                 value = g_new0 (GValue, 1);
372                 g_value_init (value, G_TYPE_STRING);
373                 g_value_set_string (value, search_string);
374
375                 g_hash_table_insert (args, g_strdup ("find-string"), value);
376         }
377
378         /* Mode */
379         if (mode != EV_WINDOW_MODE_NORMAL) {
380                 value = g_new0 (GValue, 1);
381                 g_value_init (value, G_TYPE_UINT);
382                 g_value_set_uint (value, mode);
383
384                 g_hash_table_insert (args, g_strdup ("mode"), value);
385         }
386
387         return args;
388 }
389
390 static void
391 child_setup (gpointer user_data)
392 {
393         gchar *startup_id;
394
395         startup_id = g_strdup_printf ("_TIME%lu",
396                                       (unsigned long)GPOINTER_TO_INT (user_data));
397         g_setenv ("DESKTOP_STARTUP_ID", startup_id, TRUE);
398         g_free (startup_id);
399 }
400
401 static void
402 ev_spawn (const char     *uri,
403           GdkScreen      *screen,
404           EvLinkDest     *dest,
405           EvWindowRunMode mode,
406           const gchar    *search_string,
407           guint           timestamp)
408 {
409         gchar   *argv[6];
410         guint    arg = 0;
411         gint     i;
412         gboolean res;
413         GError  *error = NULL;
414
415         argv[arg++] = g_build_filename (BINDIR, "evince", NULL);
416
417         /* Page label */
418         if (dest) {
419                 const gchar *page_label;
420
421                 page_label = ev_link_dest_get_page_label (dest);
422                 if (page_label)
423                         argv[arg++] = g_strdup_printf ("--page-label=%s", page_label);
424                 else
425                         argv[arg++] = g_strdup_printf ("--page-label=%d",
426                                                        ev_link_dest_get_page (dest));
427         }
428
429         /* Find string */
430         if (search_string) {
431                 argv[arg++] = g_strdup_printf ("--find=%s", search_string);
432         }
433
434         /* Mode */
435         switch (mode) {
436         case EV_WINDOW_MODE_FULLSCREEN:
437                 argv[arg++] = g_strdup ("-f");
438                 break;
439         case EV_WINDOW_MODE_PRESENTATION:
440                 argv[arg++] = g_strdup ("-s");
441                 break;
442         default:
443                 break;
444         }
445
446         argv[arg++] = (gchar *)uri;
447         argv[arg] = NULL;
448
449         res = gdk_spawn_on_screen (screen, NULL /* wd */, argv, NULL /* env */,
450                                    0,
451                                    child_setup,
452                                    GINT_TO_POINTER(timestamp),
453                                    NULL, &error);
454         if (!res) {
455                 g_warning ("Error launching evince %s: %s\n", uri, error->message);
456                 g_error_free (error);
457         }
458
459         for (i = 0; i < arg - 1; i++) {
460                 g_free (argv[i]);
461         }
462 }
463
464 static GList *
465 ev_application_get_windows (EvApplication *application)
466 {
467         GList *l, *toplevels;
468         GList *windows = NULL;
469
470         toplevels = gtk_window_list_toplevels ();
471
472         for (l = toplevels; l != NULL; l = l->next) {
473                 if (EV_IS_WINDOW (l->data)) {
474                         windows = g_list_append (windows, l->data);
475                 }
476         }
477
478         g_list_free (toplevels);
479
480         return windows;
481 }
482
483 static EvWindow *
484 ev_application_get_empty_window (EvApplication *application,
485                                  GdkScreen     *screen)
486 {
487         EvWindow *empty_window = NULL;
488         GList    *windows = ev_application_get_windows (application);
489         GList    *l;
490
491         for (l = windows; l != NULL; l = l->next) {
492                 EvWindow *window = EV_WINDOW (l->data);
493
494                 if (ev_window_is_empty (window) &&
495                     gtk_window_get_screen (GTK_WINDOW (window)) == screen) {
496                         empty_window = window;
497                         break;
498                 }
499         }
500
501         g_list_free (windows);
502
503         return empty_window;
504 }
505
506
507 #ifdef ENABLE_DBUS
508 static gboolean
509 ev_application_register_uri (EvApplication *application,
510                              const gchar   *uri,
511                              GHashTable    *args,
512                              guint          timestamp)
513 {
514         DBusGProxy *proxy;
515         gchar      *owner;
516         gboolean    retval = TRUE;
517         GError     *error = NULL;
518
519         if (!application->connection)
520                 return TRUE;
521
522         proxy = dbus_g_proxy_new_for_name (application->connection,
523                                            "org.gnome.evince.Daemon",
524                                            "/org/gnome/evince/Daemon",
525                                            "org.gnome.evince.Daemon");
526         if (!dbus_g_proxy_call (proxy, "RegisterDocument", &error,
527                                 G_TYPE_STRING, uri,
528                                 G_TYPE_INVALID,
529                                 G_TYPE_STRING, &owner,
530                                 G_TYPE_INVALID)) {
531                 g_warning ("Error registering document: %s\n", error->message);
532                 g_error_free (error);
533                 g_object_unref (proxy);
534
535                 return TRUE;
536         }
537         g_object_unref (proxy);
538
539         if (*owner == ':') {
540                 /* Already registered */
541                 proxy = dbus_g_proxy_new_for_name_owner (application->connection,
542                                                          owner,
543                                                          APPLICATION_DBUS_OBJECT_PATH,
544                                                          APPLICATION_DBUS_INTERFACE,
545                                                          &error);
546                 if (proxy) {
547                         if (!dbus_g_proxy_call (proxy, "OpenURI", &error,
548                                                 G_TYPE_STRING, uri,
549                                                 dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), args,
550                                                 G_TYPE_UINT, timestamp,
551                                                 G_TYPE_INVALID,
552                                                 G_TYPE_INVALID)) {
553                                 g_warning ("%s", error->message);
554                                 g_error_free (error);
555                         }
556                         g_object_unref (proxy);
557                 } else {
558                         g_warning ("Error creating proxy: %s\n", error->message);
559                         g_error_free (error);
560                 }
561
562                 /* Do not continue opening this document */
563                 retval = FALSE;
564         }
565
566         g_free (owner);
567
568         return retval;
569 }
570
571 static void
572 ev_application_unregister_uri (EvApplication *application,
573                                const gchar   *uri)
574 {
575         DBusGProxy *proxy;
576         GError     *error = NULL;
577
578         if (!application->connection)
579                 return;
580
581         proxy = dbus_g_proxy_new_for_name (application->connection,
582                                            "org.gnome.evince.Daemon",
583                                            "/org/gnome/evince/Daemon",
584                                            "org.gnome.evince.Daemon");
585         if (!dbus_g_proxy_call (proxy, "UnregisterDocument", &error,
586                                 G_TYPE_STRING, uri,
587                                 G_TYPE_INVALID,
588                                 G_TYPE_INVALID)) {
589                 g_warning ("Error unregistering document: %s\n", error->message);
590                 g_error_free (error);
591         }
592
593         g_object_unref (proxy);
594 }
595 #endif /* ENABLE_DBUS */
596
597 static void
598 ev_application_open_uri_in_window (EvApplication  *application,
599                                    const char     *uri,
600                                    EvWindow       *ev_window,
601                                    GdkScreen      *screen,
602                                    EvLinkDest     *dest,
603                                    EvWindowRunMode mode,
604                                    const gchar    *search_string,
605                                    guint           timestamp)
606 {
607         if (screen) {
608                 ev_stock_icons_set_screen (screen);
609                 gtk_window_set_screen (GTK_WINDOW (ev_window), screen);
610         }
611
612         /* We need to load uri before showing the window, so
613            we can restore window size without flickering */
614         ev_window_open_uri (ev_window, uri, dest, mode, search_string);
615
616         if (!GTK_WIDGET_REALIZED (GTK_WIDGET (ev_window)))
617                 gtk_widget_realize (GTK_WIDGET (ev_window));
618
619 #ifdef GDK_WINDOWING_X11
620         if (timestamp <= 0)
621                 timestamp = gdk_x11_get_server_time (GTK_WIDGET (ev_window)->window);
622         gdk_x11_window_set_user_time (GTK_WIDGET (ev_window)->window, timestamp);
623
624         ev_document_fc_mutex_lock ();
625         gtk_window_present (GTK_WINDOW (ev_window));
626         ev_document_fc_mutex_unlock ();
627 #else
628         ev_document_fc_mutex_lock ();
629         gtk_window_present_with_time (GTK_WINDOW (ev_window), timestamp);
630         ev_document_fc_mutex_unlock ();
631 #endif /* GDK_WINDOWING_X11 */
632 }
633
634 /**
635  * ev_application_open_uri_at_dest:
636  * @application: The instance of the application.
637  * @uri: The uri to be opened.
638  * @screen: Thee screen where the link will be shown.
639  * @dest: The #EvLinkDest of the document.
640  * @mode: The run mode of the window.
641  * @timestamp: Current time value.
642  */
643 void
644 ev_application_open_uri_at_dest (EvApplication  *application,
645                                  const char     *uri,
646                                  GdkScreen      *screen,
647                                  EvLinkDest     *dest,
648                                  EvWindowRunMode mode,
649                                  const gchar    *search_string,
650                                  guint           timestamp)
651 {
652         EvWindow *ev_window;
653
654         g_return_if_fail (uri != NULL);
655
656         if (application->uri && strcmp (application->uri, uri) != 0) {
657                 /* spawn a new evince process */
658                 ev_spawn (uri, screen, dest, mode, search_string, timestamp);
659                 return;
660         } else {
661 #ifdef ENABLE_DBUS
662                 GHashTable *args = build_args (screen, dest, mode, search_string);
663                 gboolean    ret;
664
665                 /* Register the uri or send OpenURI to
666                  * remote instance if already registered
667                  */
668                 ret = ev_application_register_uri (application, uri, args, timestamp);
669                 g_hash_table_destroy (args);
670                 if (!ret)
671                         return;
672 #endif /* ENABLE_DBUS */
673
674                 ev_window = ev_application_get_empty_window (application, screen);
675                 if (!ev_window)
676                         ev_window = EV_WINDOW (ev_window_new ());
677         }
678
679         application->uri = g_strdup (uri);
680
681         ev_application_open_uri_in_window (application, uri, ev_window,
682                                            screen, dest, mode,
683                                            search_string,
684                                            timestamp);
685 }
686
687 /**
688  * ev_application_open_window:
689  * @application: The instance of the application.
690  * @timestamp: Current time value.
691  *
692  * Creates a new window
693  */
694 void
695 ev_application_open_window (EvApplication *application,
696                             GdkScreen     *screen,
697                             guint32        timestamp)
698 {
699         GtkWidget *new_window = ev_window_new ();
700
701         if (screen) {
702                 ev_stock_icons_set_screen (screen);
703                 gtk_window_set_screen (GTK_WINDOW (new_window), screen);
704         }
705
706         if (!GTK_WIDGET_REALIZED (new_window))
707                 gtk_widget_realize (new_window);
708
709 #ifdef GDK_WINDOWING_X11
710         if (timestamp <= 0)
711                 timestamp = gdk_x11_get_server_time (new_window->window);
712         gdk_x11_window_set_user_time (new_window->window, timestamp);
713
714         gtk_window_present (GTK_WINDOW (new_window));
715 #else
716         gtk_window_present_with_time (GTK_WINDOW (new_window), timestamp);
717 #endif /* GDK_WINDOWING_X11 */
718 }
719
720 /**
721  * ev_application_open_uri:
722  * @application: The instance of the application.
723  * @uri: The uri to be opened
724  * @args: A #GHashTable with the arguments data.
725  * @timestamp: Current time value.
726  * @error: The #GError facility.
727  */
728 static gboolean
729 ev_application_open_uri (EvApplication  *application,
730                          const char     *uri,
731                          GHashTable     *args,
732                          guint           timestamp,
733                          GError        **error)
734 {
735         GList           *windows, *l;
736         EvLinkDest      *dest = NULL;
737         EvWindowRunMode  mode = EV_WINDOW_MODE_NORMAL;
738         const gchar     *search_string = NULL;
739         GdkScreen       *screen = NULL;
740
741         g_assert (application->uri != NULL);
742
743         /* FIXME: we don't need uri anymore,
744          * maybe this method should be renamed
745          * as reload, refresh or something like that
746          */
747         if (!application->uri || strcmp (application->uri, uri)) {
748                 g_warning ("Invalid uri: %s, expected %s\n",
749                            uri, application->uri);
750                 return TRUE;
751         }
752
753         if (args) {
754                 screen = get_screen_from_args (args);
755                 dest = get_destination_from_args (args);
756                 mode = get_window_run_mode_from_args (args);
757                 search_string = get_find_string_from_args (args);
758         }
759
760         windows = ev_application_get_windows (application);
761         for (l = windows; l != NULL; l = g_list_next (l)) {
762                 EvWindow *ev_window = EV_WINDOW (l->data);
763
764                 ev_application_open_uri_in_window (application, uri, ev_window,
765                                                    screen, dest, mode,
766                                                    search_string,
767                                                    timestamp);
768         }
769         g_list_free (windows);
770
771         if (dest)
772                 g_object_unref (dest);
773
774         return TRUE;
775 }
776
777 void
778 ev_application_open_uri_list (EvApplication *application,
779                               GSList        *uri_list,
780                               GdkScreen     *screen,
781                               guint          timestamp)
782 {
783         GSList *l;
784
785         for (l = uri_list; l != NULL; l = l->next) {
786                 ev_application_open_uri_at_dest (application, (char *)l->data,
787                                                  screen, NULL, 0, NULL,
788                                                  timestamp);
789         }
790 }
791
792 void
793 ev_application_shutdown (EvApplication *application)
794 {
795         if (application->uri) {
796 #ifdef ENABLE_DBUS
797                 ev_application_unregister_uri (application,
798                                                application->uri);
799 #endif
800                 g_free (application->uri);
801                 application->uri = NULL;
802         }
803
804         if (application->accel_map_file) {
805                 gtk_accel_map_save (application->accel_map_file);
806                 g_free (application->accel_map_file);
807                 application->accel_map_file = NULL;
808         }
809         
810         if (application->toolbars_model) {
811                 g_object_unref (application->toolbars_model);
812                 g_free (application->toolbars_file);
813                 application->toolbars_model = NULL;
814                 application->toolbars_file = NULL;
815         }
816
817 #ifdef ENABLE_DBUS
818         if (application->keys) {
819                 g_object_unref (application->keys);
820                 application->keys = NULL;
821         }
822 #endif /* ENABLE_DBUS */
823         
824         g_free (application->dot_dir);
825         application->dot_dir = NULL;
826         g_free (application->data_dir);
827         application->data_dir = NULL;
828         g_free (application->filechooser_open_uri);
829         application->filechooser_open_uri = NULL;
830         g_free (application->filechooser_save_uri);
831         application->filechooser_save_uri = NULL;
832
833         g_object_unref (application);
834         instance = NULL;
835         
836         gtk_main_quit ();
837 }
838
839 static void
840 ev_application_class_init (EvApplicationClass *ev_application_class)
841 {
842 #ifdef ENABLE_DBUS
843         dbus_g_object_type_install_info (EV_TYPE_APPLICATION,
844                                          &dbus_glib_ev_application_object_info);
845 #endif
846 }
847
848 static void
849 ev_application_init (EvApplication *ev_application)
850 {
851         gint i;
852         const gchar *home_dir;
853         gchar *toolbar_path;
854         GError *error = NULL;
855
856         ev_application->dot_dir = g_build_filename (g_get_home_dir (),
857                                                     ".gnome2",
858                                                     "evince",
859                                                     NULL);
860
861         /* FIXME: why make this fatal? */
862         if (!ev_dir_ensure_exists (ev_application->dot_dir, 0700))
863                 exit (1);
864
865 #ifdef G_OS_WIN32
866 {
867         gchar *dir;
868
869         dir = g_win32_get_package_installation_directory_of_module (NULL);
870         ev_application->data_dir = g_build_filename (dir, "share", "evince", NULL);
871         g_free (dir);
872 }
873 #else
874         ev_application->data_dir = g_strdup (DATADIR);
875 #endif
876
877         ev_application_init_session (ev_application);
878
879         home_dir = g_get_home_dir ();
880         if (home_dir) {
881                 ev_application->accel_map_file = g_build_filename (home_dir,
882                                                                    ".gnome2",
883                                                                    "accels",
884                                                                    "evince",
885                                                                    NULL);
886                 gtk_accel_map_load (ev_application->accel_map_file);
887         }
888         
889         ev_application->toolbars_model = egg_toolbars_model_new ();
890
891         ev_application->toolbars_file = g_build_filename
892                         (ev_application->dot_dir, "evince_toolbar.xml", NULL);
893
894         toolbar_path = g_build_filename (ev_application->data_dir,
895                                          "evince-toolbar.xml", NULL);
896         egg_toolbars_model_load_names (ev_application->toolbars_model,
897                                        toolbar_path);
898
899         if (!egg_toolbars_model_load_toolbars (ev_application->toolbars_model,
900                                                ev_application->toolbars_file)) {
901                 egg_toolbars_model_load_toolbars (ev_application->toolbars_model,
902                                                   toolbar_path);
903         }
904         g_free (toolbar_path);
905
906         /* Open item doesn't exist anymore,
907          * convert it to OpenRecent for compatibility
908          */
909         for (i = 0; i < egg_toolbars_model_n_items (ev_application->toolbars_model, 0); i++) {
910                 const gchar *item;
911                 
912                 item = egg_toolbars_model_item_nth (ev_application->toolbars_model, 0, i);
913                 if (g_ascii_strcasecmp (item, "FileOpen") == 0) {
914                         egg_toolbars_model_remove_item (ev_application->toolbars_model, 0, i);
915                         egg_toolbars_model_add_item (ev_application->toolbars_model, 0, i,
916                                                      "FileOpenRecent");
917                         ev_application_save_toolbars_model (ev_application);
918                         break;
919                 }
920         }
921
922         egg_toolbars_model_set_flags (ev_application->toolbars_model, 0,
923                                       EGG_TB_MODEL_NOT_REMOVABLE);
924
925 #ifdef ENABLE_DBUS
926         ev_application->connection = dbus_g_bus_get (DBUS_BUS_STARTER, &error);
927         if (ev_application->connection) {
928                 dbus_g_connection_register_g_object (ev_application->connection,
929                                                      APPLICATION_DBUS_OBJECT_PATH,
930                                                      G_OBJECT (ev_application));
931                 ev_application->scr_saver = totem_scrsaver_new (ev_application->connection);
932         } else {
933                 g_warning ("Error connection to DBus: %s\n", error->message);
934                 g_error_free (error);
935         }
936         ev_application->keys = ev_media_player_keys_new ();
937 #endif /* ENABLE_DBUS */
938 }
939
940 gboolean
941 ev_application_has_window (EvApplication *application)
942 {
943         GList   *windows = ev_application_get_windows (application);
944         gboolean retval = windows != NULL;
945
946         g_list_free (windows);
947
948         return retval;
949 }
950
951 const gchar *
952 ev_application_get_uri (EvApplication *application)
953 {
954         return application->uri;
955 }
956
957 /**
958  * ev_application_get_media_keys:
959  * @application: The instance of the application.
960  *
961  * It gives you access to the media player keys handler object.
962  *
963  * Returns: A #EvMediaPlayerKeys.
964  */
965 GObject *
966 ev_application_get_media_keys (EvApplication *application)
967 {
968 #ifdef ENABLE_DBUS
969         return G_OBJECT (application->keys);
970 #else
971         return NULL;
972 #endif /* ENABLE_DBUS */
973 }
974
975 EggToolbarsModel *
976 ev_application_get_toolbars_model (EvApplication *application)
977 {
978         return application->toolbars_model;
979 }
980
981 void
982 ev_application_save_toolbars_model (EvApplication *application)
983 {
984         egg_toolbars_model_save_toolbars (application->toolbars_model,
985                                           application->toolbars_file, "1.0");
986 }
987
988 void
989 ev_application_set_filechooser_uri (EvApplication       *application,
990                                     GtkFileChooserAction action,
991                                     const gchar         *uri)
992 {
993         if (action == GTK_FILE_CHOOSER_ACTION_OPEN) {
994                 g_free (application->filechooser_open_uri);
995                 application->filechooser_open_uri = g_strdup (uri);
996         } else if (action == GTK_FILE_CHOOSER_ACTION_SAVE) {
997                 g_free (application->filechooser_save_uri);
998                 application->filechooser_save_uri = g_strdup (uri);
999         }
1000 }
1001
1002 const gchar *
1003 ev_application_get_filechooser_uri (EvApplication       *application,
1004                                     GtkFileChooserAction action)
1005 {
1006         if (action == GTK_FILE_CHOOSER_ACTION_OPEN) {
1007                 if (application->filechooser_open_uri)
1008                         return application->filechooser_open_uri;
1009         } else if (action == GTK_FILE_CHOOSER_ACTION_SAVE) {
1010                 if (application->filechooser_save_uri)
1011                         return application->filechooser_save_uri;
1012         }
1013
1014         return NULL;
1015 }
1016
1017 void
1018 ev_application_screensaver_enable (EvApplication *application)
1019 {
1020         if (application->scr_saver)
1021                 totem_scrsaver_enable (application->scr_saver); 
1022 }
1023
1024 void
1025 ev_application_screensaver_disable (EvApplication *application)
1026 {
1027         if (application->scr_saver)
1028                 totem_scrsaver_disable (application->scr_saver);        
1029 }
1030
1031 const gchar *
1032 ev_application_get_dot_dir (EvApplication   *application)
1033 {
1034         return application->dot_dir;
1035 }
1036
1037 const gchar *
1038 ev_application_get_data_dir (EvApplication   *application)
1039 {
1040         return application->data_dir;
1041 }