]> www.fi.muni.cz Git - evince.git/blob - shell/ev-window.c
shell: Add bookmarks menu to add and show internal bookmarks
[evince.git] / shell / ev-window.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
2 /* this file is part of evince, a gnome document viewer
3  *
4  *  Copyright (C) 2009 Juanjo Marín <juanj.marin@juntadeandalucia.es>
5  *  Copyright (C) 2008 Carlos Garcia Campos
6  *  Copyright (C) 2004 Martin Kretzschmar
7  *  Copyright (C) 2004 Red Hat, Inc.
8  *  Copyright (C) 2000, 2001, 2002, 2003, 2004 Marco Pesenti Gritti
9  *  Copyright © 2003, 2004, 2005, 2009 Christian Persch
10  *
11  *  Author:
12  *    Martin Kretzschmar <martink@gnome.org>
13  *
14  * Evince is free software; you can redistribute it and/or modify it
15  * under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  *
19  * Evince is distributed in the hope that it will be useful, but
20  * WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27  */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <errno.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <math.h>
38
39 #include <glib/gstdio.h>
40 #include <glib/gi18n.h>
41 #include <gio/gio.h>
42 #include <gtk/gtk.h>
43
44 #include "egg-editable-toolbar.h"
45 #include "egg-toolbar-editor.h"
46 #include "egg-toolbars-model.h"
47
48 #include "eggfindbar.h"
49
50 #include "ephy-zoom-action.h"
51 #include "ephy-zoom.h"
52
53 #include "ev-application.h"
54 #include "ev-document-factory.h"
55 #include "ev-document-find.h"
56 #include "ev-document-fonts.h"
57 #include "ev-document-images.h"
58 #include "ev-document-links.h"
59 #include "ev-document-annotations.h"
60 #include "ev-document-type-builtins.h"
61 #include "ev-document-misc.h"
62 #include "ev-file-exporter.h"
63 #include "ev-file-helpers.h"
64 #include "ev-file-monitor.h"
65 #include "ev-history.h"
66 #include "ev-image.h"
67 #include "ev-job-scheduler.h"
68 #include "ev-jobs.h"
69 #include "ev-message-area.h"
70 #include "ev-metadata.h"
71 #include "ev-navigation-action.h"
72 #include "ev-open-recent-action.h"
73 #include "ev-page-action.h"
74 #include "ev-password-view.h"
75 #include "ev-properties-dialog.h"
76 #include "ev-sidebar-annotations.h"
77 #include "ev-sidebar-attachments.h"
78 #include "ev-sidebar.h"
79 #include "ev-sidebar-links.h"
80 #include "ev-sidebar-page.h"
81 #include "ev-sidebar-thumbnails.h"
82 #include "ev-sidebar-layers.h"
83 #include "ev-stock-icons.h"
84 #include "ev-utils.h"
85 #include "ev-keyring.h"
86 #include "ev-view.h"
87 #include "ev-view-presentation.h"
88 #include "ev-view-type-builtins.h"
89 #include "ev-window.h"
90 #include "ev-window-title.h"
91 #include "ev-print-operation.h"
92 #include "ev-progress-message-area.h"
93 #include "ev-annotation-properties-dialog.h"
94 #include "ev-bookmarks.h"
95 #include "ev-bookmark-action.h"
96
97 #ifdef ENABLE_DBUS
98 #include "ev-media-player-keys.h"
99 #endif /* ENABLE_DBUS */
100
101 typedef enum {
102         PAGE_MODE_DOCUMENT,
103         PAGE_MODE_PASSWORD
104 } EvWindowPageMode;
105
106 typedef enum {
107         EV_CHROME_MENUBAR       = 1 << 0,
108         EV_CHROME_TOOLBAR       = 1 << 1,
109         EV_CHROME_FINDBAR       = 1 << 2,
110         EV_CHROME_RAISE_TOOLBAR = 1 << 3,
111         EV_CHROME_FULLSCREEN_TOOLBAR    = 1 << 4,
112         EV_CHROME_SIDEBAR       = 1 << 5,
113         EV_CHROME_NORMAL        = EV_CHROME_MENUBAR | EV_CHROME_TOOLBAR | EV_CHROME_SIDEBAR
114 } EvChrome;
115
116 typedef enum {
117         EV_SAVE_DOCUMENT,
118         EV_SAVE_ATTACHMENT,
119         EV_SAVE_IMAGE
120 } EvSaveType;
121
122 struct _EvWindowPrivate {
123         /* UI */
124         EvChrome chrome;
125
126         GtkWidget *main_box;
127         GtkWidget *menubar;
128         GtkWidget *toolbar;
129         GtkWidget *hpaned;
130         GtkWidget *view_box;
131         GtkWidget *sidebar;
132         GtkWidget *find_bar;
133         GtkWidget *scrolled_window;
134         GtkWidget *view;
135         GtkWidget *presentation_view;
136         GtkWidget *message_area;
137         GtkWidget *password_view;
138         GtkWidget *sidebar_thumbs;
139         GtkWidget *sidebar_links;
140         GtkWidget *sidebar_attachments;
141         GtkWidget *sidebar_layers;
142         GtkWidget *sidebar_annots;
143
144         /* Settings */
145         GSettings *settings;
146         GSettings *default_settings;
147         GSettings *lockdown_settings;
148
149         /* Menubar accels */
150         guint           menubar_accel_keyval;
151         GdkModifierType menubar_accel_modifier;
152
153         /* Progress Messages */
154         guint progress_idle;
155         GCancellable *progress_cancellable;
156
157         /* Dialogs */
158         GtkWidget *properties;
159         GtkWidget *print_dialog;
160
161         /* UI Builders */
162         GtkActionGroup   *action_group;
163         GtkActionGroup   *view_popup_action_group;
164         GtkActionGroup   *attachment_popup_action_group;
165         GtkRecentManager *recent_manager;
166         GtkActionGroup   *recent_action_group;
167         guint             recent_ui_id;
168         GtkActionGroup   *bookmarks_action_group;
169         guint             bookmarks_ui_id;
170         GtkUIManager     *ui_manager;
171
172         /* Fullscreen mode */
173         GtkWidget *fullscreen_toolbar;
174
175         /* Popup view */
176         GtkWidget    *view_popup;
177         EvLink       *link;
178         EvImage      *image;
179         EvAnnotation *annot;
180
181         /* Popup attachment */
182         GtkWidget    *attachment_popup;
183         GList        *attach_list;
184
185         /* Document */
186         EvDocumentModel *model;
187         char *uri;
188         glong uri_mtime;
189         char *local_uri;
190         gboolean in_reload;
191         EvFileMonitor *monitor;
192         guint setup_document_idle;
193         
194         EvDocument *document;
195         EvHistory *history;
196         EvWindowPageMode page_mode;
197         EvWindowTitle *title;
198         EvMetadata *metadata;
199         EvBookmarks *bookmarks;
200         gboolean is_new_doc;
201
202         /* Load params */
203         EvLinkDest       *dest;
204         gchar            *search_string;
205         EvWindowRunMode   window_mode;
206
207         EvJob            *load_job;
208         EvJob            *reload_job;
209         EvJob            *thumbnail_job;
210         EvJob            *save_job;
211         EvJob            *find_job;
212
213         /* Printing */
214         GQueue           *print_queue;
215         GtkPrintSettings *print_settings;
216         GtkPageSetup     *print_page_setup;
217         gboolean          close_after_print;
218
219 #ifdef ENABLE_DBUS
220         /* DBus */
221         guint  dbus_object_id;
222         gchar *dbus_object_path;
223 #endif
224 };
225
226 #define EV_WINDOW_GET_PRIVATE(object) \
227         (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_WINDOW, EvWindowPrivate))
228
229 #define EV_WINDOW_IS_PRESENTATION(w) (w->priv->presentation_view != NULL)
230
231 #define PAGE_SELECTOR_ACTION    "PageSelector"
232 #define ZOOM_CONTROL_ACTION     "ViewZoom"
233 #define NAVIGATION_ACTION       "Navigation"
234
235 #define GS_LOCKDOWN_SCHEMA_NAME  "org.gnome.desktop.lockdown"
236 #define GS_LOCKDOWN_SAVE         "disable-save-to-disk"
237 #define GS_LOCKDOWN_PRINT        "disable-printing"
238 #define GS_LOCKDOWN_PRINT_SETUP  "disable-print-setup"
239
240 #ifdef ENABLE_DBUS
241 #define EV_WINDOW_DBUS_OBJECT_PATH "/org/gnome/evince/Window/%d"
242 #define EV_WINDOW_DBUS_INTERFACE   "org.gnome.evince.Window"
243 #endif
244
245 #define GS_SCHEMA_NAME           "org.gnome.Evince"
246 #define GS_OVERRIDE_RESTRICTIONS "override-restrictions"
247
248 #define SIDEBAR_DEFAULT_SIZE    132
249 #define LINKS_SIDEBAR_ID "links"
250 #define THUMBNAILS_SIDEBAR_ID "thumbnails"
251 #define ATTACHMENTS_SIDEBAR_ID "attachments"
252 #define LAYERS_SIDEBAR_ID "layers"
253 #define ANNOTS_SIDEBAR_ID "annotations"
254
255 #define EV_PRINT_SETTINGS_FILE  "print-settings"
256 #define EV_PRINT_SETTINGS_GROUP "Print Settings"
257 #define EV_PAGE_SETUP_GROUP     "Page Setup"
258
259 #define EV_TOOLBARS_FILENAME "evince-toolbar.xml"
260
261 #define MIN_SCALE 0.05409
262 #define PAGE_CACHE_SIZE 52428800 /* 50MB */
263
264 #define MAX_RECENT_ITEM_LEN (40)
265
266 static const gchar *document_print_settings[] = {
267         GTK_PRINT_SETTINGS_N_COPIES,
268         GTK_PRINT_SETTINGS_COLLATE,
269         GTK_PRINT_SETTINGS_REVERSE,
270         GTK_PRINT_SETTINGS_NUMBER_UP,
271         GTK_PRINT_SETTINGS_SCALE,
272         GTK_PRINT_SETTINGS_PRINT_PAGES,
273         GTK_PRINT_SETTINGS_PAGE_RANGES,
274         GTK_PRINT_SETTINGS_PAGE_SET,
275         GTK_PRINT_SETTINGS_OUTPUT_URI
276 };
277
278 static void     ev_window_update_actions                (EvWindow         *ev_window);
279 static void     ev_window_sidebar_visibility_changed_cb (EvSidebar        *ev_sidebar,
280                                                          GParamSpec       *pspec,
281                                                          EvWindow         *ev_window);
282 static void     ev_window_view_toolbar_cb               (GtkAction        *action,
283                                                          EvWindow         *ev_window);
284 static void     ev_window_set_page_mode                 (EvWindow         *window,
285                                                          EvWindowPageMode  page_mode);
286 static void     ev_window_load_job_cb                   (EvJob            *job,
287                                                          gpointer          data);
288 static void     ev_window_reload_document               (EvWindow         *window,
289                                                          EvLinkDest *dest);
290 static void     ev_window_reload_job_cb                 (EvJob            *job,
291                                                          EvWindow         *window);
292 static void     ev_window_set_icon_from_thumbnail       (EvJobThumbnail   *job,
293                                                          EvWindow         *ev_window);
294 static void     ev_window_save_job_cb                   (EvJob            *save,
295                                                          EvWindow         *window);
296 static void     ev_window_sizing_mode_changed_cb        (EvDocumentModel  *model,
297                                                          GParamSpec       *pspec,
298                                                          EvWindow         *ev_window);
299 static void     ev_window_zoom_changed_cb               (EvDocumentModel  *model,
300                                                          GParamSpec       *pspec,
301                                                          EvWindow         *ev_window);
302 static void     ev_window_add_recent                    (EvWindow         *window,
303                                                          const char       *filename);
304 static void     ev_window_run_fullscreen                (EvWindow         *window);
305 static void     ev_window_stop_fullscreen               (EvWindow         *window,
306                                                          gboolean          unfullscreen_window);
307 static void     ev_window_cmd_view_fullscreen           (GtkAction        *action,
308                                                          EvWindow         *window);
309 static void     ev_window_run_presentation              (EvWindow         *window);
310 static void     ev_window_stop_presentation             (EvWindow         *window,
311                                                          gboolean          unfullscreen_window);
312 static void     ev_window_cmd_view_presentation         (GtkAction        *action,
313                                                          EvWindow         *window);
314 static void     ev_view_popup_cmd_open_link             (GtkAction        *action,
315                                                          EvWindow         *window);
316 static void     ev_view_popup_cmd_open_link_new_window  (GtkAction        *action,
317                                                          EvWindow         *window);
318 static void     ev_view_popup_cmd_copy_link_address     (GtkAction        *action,
319                                                          EvWindow         *window);
320 static void     ev_view_popup_cmd_save_image_as         (GtkAction        *action,
321                                                          EvWindow         *window);
322 static void     ev_view_popup_cmd_copy_image            (GtkAction        *action,
323                                                          EvWindow         *window);
324 static void     ev_view_popup_cmd_annot_properties      (GtkAction        *action,
325                                                          EvWindow         *window);
326 static void     ev_attachment_popup_cmd_open_attachment (GtkAction        *action,
327                                                          EvWindow         *window);
328 static void     ev_attachment_popup_cmd_save_attachment_as (GtkAction     *action, 
329                                                          EvWindow         *window);
330 static void     ev_window_cmd_view_best_fit             (GtkAction        *action, 
331                                                          EvWindow         *ev_window);
332 static void     ev_window_cmd_view_page_width           (GtkAction        *action, 
333                                                          EvWindow         *ev_window);
334 static void     view_handle_link_cb                     (EvView           *view, 
335                                                          EvLink           *link, 
336                                                          EvWindow         *window);
337 static void     ev_window_update_find_status_message    (EvWindow         *ev_window);
338 static void     ev_window_cmd_edit_find                 (GtkAction        *action,
339                                                          EvWindow         *ev_window);
340 static void     find_bar_search_changed_cb              (EggFindBar       *find_bar,
341                                                          GParamSpec       *param,
342                                                          EvWindow         *ev_window);
343 static void     ev_window_load_file_remote              (EvWindow         *ev_window,
344                                                          GFile            *source_file);
345 static void     ev_window_media_player_key_pressed      (EvWindow         *window,
346                                                          const gchar      *key,
347                                                          gpointer          user_data);
348 static void     ev_window_update_max_min_scale          (EvWindow         *window);
349 #ifdef ENABLE_DBUS
350 static void     ev_window_emit_closed                   (EvWindow         *window);
351 static void     ev_window_emit_doc_loaded               (EvWindow         *window);
352 #endif
353 static void     ev_window_setup_bookmarks               (EvWindow         *window);
354
355 static guint ev_window_n_copies = 0;
356
357 G_DEFINE_TYPE (EvWindow, ev_window, GTK_TYPE_WINDOW)
358
359 static gdouble
360 get_screen_dpi (EvWindow *window)
361 {
362         GdkScreen *screen;
363
364         screen = gtk_window_get_screen (GTK_WINDOW (window));
365         return ev_document_misc_get_screen_dpi (screen);
366 }
367
368 static void
369 ev_window_set_action_sensitive (EvWindow   *ev_window,
370                                 const char *name,
371                                 gboolean    sensitive)
372 {
373         GtkAction *action = gtk_action_group_get_action (ev_window->priv->action_group,
374                                                          name);
375         gtk_action_set_sensitive (action, sensitive);
376 }
377
378
379 static void
380 ev_window_setup_action_sensitivity (EvWindow *ev_window)
381 {
382         EvDocument *document = ev_window->priv->document;
383         const EvDocumentInfo *info = NULL;
384         gboolean has_document = FALSE;
385         gboolean ok_to_print = TRUE;
386         gboolean ok_to_copy = TRUE;
387         gboolean has_properties = TRUE;
388         gboolean override_restrictions = TRUE;
389         gboolean can_get_text = FALSE;
390         gboolean has_pages = FALSE;
391         gboolean can_find = FALSE;
392
393         if (document) {
394                 has_document = TRUE;
395                 has_pages = ev_document_get_n_pages (document) > 0;
396                 info = ev_document_get_info (document);
397         }
398
399         if (!info || info->fields_mask == 0) {
400                 has_properties = FALSE;
401         }
402
403         if (has_document && EV_IS_SELECTION (document)) {
404                 can_get_text = TRUE;
405         }
406         
407         if (has_pages && EV_IS_DOCUMENT_FIND (document)) {
408                 can_find = TRUE;
409         }
410
411         if (has_document && ev_window->priv->settings) {
412                 override_restrictions =
413                         g_settings_get_boolean (ev_window->priv->settings,
414                                                 GS_OVERRIDE_RESTRICTIONS);
415         }
416
417         if (!override_restrictions && info && info->fields_mask & EV_DOCUMENT_INFO_PERMISSIONS) {
418                 ok_to_print = (info->permissions & EV_DOCUMENT_PERMISSIONS_OK_TO_PRINT);
419                 ok_to_copy = (info->permissions & EV_DOCUMENT_PERMISSIONS_OK_TO_COPY);
420         }
421
422         if (has_document && !ev_print_operation_exists_for_document(document))
423                 ok_to_print = FALSE;
424
425         if (has_document && ev_window->priv->lockdown_settings &&
426             g_settings_get_boolean (ev_window->priv->lockdown_settings, GS_LOCKDOWN_SAVE)) {
427                 ok_to_copy = FALSE;
428         }
429
430         if (has_document && ev_window->priv->lockdown_settings &&
431             g_settings_get_boolean (ev_window->priv->lockdown_settings, GS_LOCKDOWN_PRINT)) {
432                 ok_to_print = FALSE;
433         }
434
435         /* File menu */
436         ev_window_set_action_sensitive (ev_window, "FileOpenCopy", has_document);
437         ev_window_set_action_sensitive (ev_window, "FileSaveAs", has_document && ok_to_copy);
438         ev_window_set_action_sensitive (ev_window, "FilePrint", has_pages && ok_to_print);
439         ev_window_set_action_sensitive (ev_window, "FileProperties", has_document && has_properties);
440
441         /* Edit menu */
442         ev_window_set_action_sensitive (ev_window, "EditSelectAll", has_pages && can_get_text);
443         ev_window_set_action_sensitive (ev_window, "EditFind", can_find);
444         ev_window_set_action_sensitive (ev_window, "Slash", can_find);
445         ev_window_set_action_sensitive (ev_window, "EditRotateLeft", has_pages);
446         ev_window_set_action_sensitive (ev_window, "EditRotateRight", has_pages);
447
448         /* View menu */
449         ev_window_set_action_sensitive (ev_window, "ViewContinuous", has_pages);
450         ev_window_set_action_sensitive (ev_window, "ViewDual", has_pages);
451         ev_window_set_action_sensitive (ev_window, "ViewBestFit", has_pages);
452         ev_window_set_action_sensitive (ev_window, "ViewPageWidth", has_pages);
453         ev_window_set_action_sensitive (ev_window, "ViewReload", has_pages);
454         ev_window_set_action_sensitive (ev_window, "ViewAutoscroll", has_pages);
455         ev_window_set_action_sensitive (ev_window, "ViewInvertedColors", has_pages);
456
457         /* Bookmarks menu */
458         ev_window_set_action_sensitive (ev_window, "BookmarksAdd",
459                                         has_pages && ev_window->priv->bookmarks);
460
461         /* Toolbar-specific actions: */
462         ev_window_set_action_sensitive (ev_window, PAGE_SELECTOR_ACTION, has_pages);
463         ev_window_set_action_sensitive (ev_window, ZOOM_CONTROL_ACTION,  has_pages);
464         ev_window_set_action_sensitive (ev_window, NAVIGATION_ACTION,  FALSE);
465
466         ev_window_update_actions (ev_window);
467 }
468
469 static void
470 ev_window_update_actions (EvWindow *ev_window)
471 {
472         EvView *view = EV_VIEW (ev_window->priv->view);
473         int n_pages = 0, page = -1;
474         gboolean has_pages = FALSE;
475         gboolean presentation_mode;
476         gboolean can_find_in_page = FALSE;
477         EvSizingMode sizing_mode;
478
479         if (ev_window->priv->document) {
480                 page = ev_document_model_get_page (ev_window->priv->model);
481                 n_pages = ev_document_get_n_pages (ev_window->priv->document);
482                 has_pages = n_pages > 0;
483         }
484
485         can_find_in_page = (ev_window->priv->find_job &&
486                             ev_job_find_has_results (EV_JOB_FIND (ev_window->priv->find_job)));
487
488         ev_window_set_action_sensitive (ev_window, "EditCopy",
489                                         has_pages &&
490                                         ev_view_get_has_selection (view));
491         ev_window_set_action_sensitive (ev_window, "EditFindNext",
492                                         has_pages && can_find_in_page);
493         ev_window_set_action_sensitive (ev_window, "EditFindPrevious",
494                                         has_pages && can_find_in_page);
495         ev_window_set_action_sensitive (ev_window, "F3",
496                                         has_pages && can_find_in_page);
497
498         presentation_mode = EV_WINDOW_IS_PRESENTATION (ev_window);
499         
500         ev_window_set_action_sensitive (ev_window, "ViewZoomIn",
501                                         has_pages &&
502                                         ev_view_can_zoom_in (view) &&
503                                         !presentation_mode);
504         ev_window_set_action_sensitive (ev_window, "ViewZoomOut",
505                                         has_pages &&
506                                         ev_view_can_zoom_out (view) &&
507                                         !presentation_mode);
508         
509         /* Go menu */
510         if (has_pages) {
511                 ev_window_set_action_sensitive (ev_window, "GoPreviousPage", page > 0);
512                 ev_window_set_action_sensitive (ev_window, "GoNextPage", page < n_pages - 1);
513                 ev_window_set_action_sensitive (ev_window, "GoFirstPage", page > 0);
514                 ev_window_set_action_sensitive (ev_window, "GoLastPage", page < n_pages - 1);
515         } else {
516                 ev_window_set_action_sensitive (ev_window, "GoFirstPage", FALSE);
517                 ev_window_set_action_sensitive (ev_window, "GoPreviousPage", FALSE);
518                 ev_window_set_action_sensitive (ev_window, "GoNextPage", FALSE);
519                 ev_window_set_action_sensitive (ev_window, "GoLastPage", FALSE);
520         }
521
522         sizing_mode = ev_document_model_get_sizing_mode (ev_window->priv->model);
523         if (has_pages && sizing_mode != EV_SIZING_FIT_WIDTH && sizing_mode != EV_SIZING_BEST_FIT) {
524                 GtkAction *action;
525                 float      zoom;
526                 float      real_zoom;
527
528                 action = gtk_action_group_get_action (ev_window->priv->action_group,
529                                                       ZOOM_CONTROL_ACTION);
530
531                 real_zoom = ev_document_model_get_scale (ev_window->priv->model);
532                 real_zoom *= 72.0 / get_screen_dpi (ev_window);
533                 zoom = ephy_zoom_get_nearest_zoom_level (real_zoom);
534
535                 ephy_zoom_action_set_zoom_level (EPHY_ZOOM_ACTION (action), zoom);
536         }
537 }
538
539 static void
540 ev_window_set_view_accels_sensitivity (EvWindow *window, gboolean sensitive)
541 {
542         gboolean can_find;
543
544         can_find = window->priv->document && 
545             EV_IS_DOCUMENT_FIND (window->priv->document);
546
547         if (window->priv->action_group) {
548                 ev_window_set_action_sensitive (window, "PageDown", sensitive);
549                 ev_window_set_action_sensitive (window, "PageUp", sensitive);
550                 ev_window_set_action_sensitive (window, "Space", sensitive);
551                 ev_window_set_action_sensitive (window, "ShiftSpace", sensitive);
552                 ev_window_set_action_sensitive (window, "BackSpace", sensitive);
553                 ev_window_set_action_sensitive (window, "ShiftBackSpace", sensitive);
554                 ev_window_set_action_sensitive (window, "Return", sensitive);
555                 ev_window_set_action_sensitive (window, "ShiftReturn", sensitive);
556                 ev_window_set_action_sensitive (window, "Plus", sensitive);
557                 ev_window_set_action_sensitive (window, "Minus", sensitive);
558                 ev_window_set_action_sensitive (window, "KpPlus", sensitive);
559                 ev_window_set_action_sensitive (window, "KpMinus", sensitive);
560                 ev_window_set_action_sensitive (window, "Equal", sensitive);
561                 ev_window_set_action_sensitive (window, "p", sensitive);
562                 ev_window_set_action_sensitive (window, "n", sensitive);
563
564                 ev_window_set_action_sensitive (window, "Slash", sensitive && can_find);
565         }
566 }
567
568 static void
569 set_widget_visibility (GtkWidget *widget, gboolean visible)
570 {
571         g_assert (GTK_IS_WIDGET (widget));
572         
573         if (visible)
574                 gtk_widget_show (widget);
575         else
576                 gtk_widget_hide (widget);
577 }
578
579 static void
580 update_chrome_visibility (EvWindow *window)
581 {
582         EvWindowPrivate *priv = window->priv;
583         gboolean menubar, toolbar, findbar, fullscreen_toolbar, sidebar;
584         gboolean fullscreen_mode, presentation, fullscreen;
585
586         presentation = EV_WINDOW_IS_PRESENTATION (window);
587         fullscreen = ev_document_model_get_fullscreen (priv->model);
588         fullscreen_mode = fullscreen || presentation;
589
590         menubar = (priv->chrome & EV_CHROME_MENUBAR) != 0 && !fullscreen_mode;
591         toolbar = ((priv->chrome & EV_CHROME_TOOLBAR) != 0  || 
592                    (priv->chrome & EV_CHROME_RAISE_TOOLBAR) != 0) && !fullscreen_mode;
593         fullscreen_toolbar = ((priv->chrome & EV_CHROME_FULLSCREEN_TOOLBAR) != 0 || 
594                               (priv->chrome & EV_CHROME_RAISE_TOOLBAR) != 0) && fullscreen;
595         findbar = (priv->chrome & EV_CHROME_FINDBAR) != 0;
596         sidebar = (priv->chrome & EV_CHROME_SIDEBAR) != 0 && priv->document && !presentation;
597
598         set_widget_visibility (priv->menubar, menubar); 
599         set_widget_visibility (priv->toolbar, toolbar);
600         set_widget_visibility (priv->find_bar, findbar);
601         set_widget_visibility (priv->sidebar, sidebar);
602         
603         ev_window_set_action_sensitive (window, "EditToolbar", toolbar);
604
605         if (priv->fullscreen_toolbar != NULL) {
606                 set_widget_visibility (priv->fullscreen_toolbar, fullscreen_toolbar);
607         }
608 }
609
610 static void
611 update_chrome_flag (EvWindow *window, EvChrome flag, gboolean active)
612 {
613         EvWindowPrivate *priv = window->priv;
614         
615         if (active) {
616                 priv->chrome |= flag;
617         } else {
618                 priv->chrome &= ~flag;
619         }
620 }
621
622 static void
623 update_sizing_buttons (EvWindow *window)
624 {
625         GtkActionGroup *action_group = window->priv->action_group;
626         GtkAction *action;
627         gboolean best_fit, page_width;
628
629         switch (ev_document_model_get_sizing_mode (window->priv->model)) {
630                 case EV_SIZING_BEST_FIT:
631                         best_fit = TRUE;
632                         page_width = FALSE;
633                         break;
634                 case EV_SIZING_FIT_WIDTH:
635                         best_fit = FALSE;
636                         page_width = TRUE;
637                         break;
638                 default:
639                         best_fit = page_width = FALSE;
640                         break;
641         }
642
643         action = gtk_action_group_get_action (action_group, "ViewBestFit");
644         g_signal_handlers_block_by_func
645                 (action, G_CALLBACK (ev_window_cmd_view_best_fit), window);
646         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), best_fit);
647         g_signal_handlers_unblock_by_func
648                 (action, G_CALLBACK (ev_window_cmd_view_best_fit), window);
649
650         action = gtk_action_group_get_action (action_group, "ViewPageWidth");   
651         g_signal_handlers_block_by_func
652                 (action, G_CALLBACK (ev_window_cmd_view_page_width), window);
653         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), page_width);
654         g_signal_handlers_unblock_by_func
655                 (action, G_CALLBACK (ev_window_cmd_view_page_width), window);
656
657         action = gtk_action_group_get_action (window->priv->action_group, 
658                                               ZOOM_CONTROL_ACTION);     
659         if (best_fit) {
660                 ephy_zoom_action_set_zoom_level (EPHY_ZOOM_ACTION (action), 
661                                                  EPHY_ZOOM_BEST_FIT);
662         } else if (page_width) {
663                 ephy_zoom_action_set_zoom_level (EPHY_ZOOM_ACTION (action), 
664                                                  EPHY_ZOOM_FIT_WIDTH);
665         }
666 }
667
668 static void
669 update_chrome_actions (EvWindow *window)
670 {
671         EvWindowPrivate *priv = window->priv;
672         GtkActionGroup *action_group = priv->action_group;
673         GtkAction *action;
674
675         action= gtk_action_group_get_action (action_group, "ViewToolbar");
676         g_signal_handlers_block_by_func
677                 (action, G_CALLBACK (ev_window_view_toolbar_cb), window);
678         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
679                                       (priv->chrome & EV_CHROME_TOOLBAR) != 0);
680         g_signal_handlers_unblock_by_func
681                 (action, G_CALLBACK (ev_window_view_toolbar_cb), window);
682 }
683
684 /**
685  * ev_window_is_empty:
686  * @ev_window: The instance of the #EvWindow.
687  *
688  * It does look if there is any document loaded or if there is any job to load
689  * a document.
690  *
691  * Returns: %TRUE if there isn't any document loaded or any any documente to be
692  *          loaded, %FALSE in other case.
693  */
694 gboolean
695 ev_window_is_empty (const EvWindow *ev_window)
696 {
697         g_return_val_if_fail (EV_IS_WINDOW (ev_window), FALSE);
698
699         return (ev_window->priv->document == NULL) && 
700                 (ev_window->priv->load_job == NULL);
701 }
702
703 static void
704 ev_window_set_message_area (EvWindow  *window,
705                             GtkWidget *area)
706 {
707         if (window->priv->message_area == area)
708                 return;
709
710         if (window->priv->message_area)
711                 gtk_widget_destroy (window->priv->message_area);
712         window->priv->message_area = area;
713
714         if (!area)
715                 return;
716
717         gtk_box_pack_start (GTK_BOX (window->priv->view_box),
718                             window->priv->message_area,
719                             FALSE, FALSE, 0);
720         gtk_box_reorder_child (GTK_BOX (window->priv->view_box),
721                                window->priv->message_area, 0);
722         g_object_add_weak_pointer (G_OBJECT (window->priv->message_area),
723                                    (gpointer) &(window->priv->message_area));
724 }
725
726 static void
727 ev_window_message_area_response_cb (EvMessageArea *area,
728                                     gint           response_id,
729                                     EvWindow      *window)
730 {
731         ev_window_set_message_area (window, NULL);
732 }
733
734 static void
735 ev_window_error_message (EvWindow    *window,
736                          GError      *error,
737                          const gchar *format,
738                          ...)
739 {
740         GtkWidget *area;
741         va_list    args;
742         gchar     *msg = NULL;
743
744         if (window->priv->message_area)
745                 return;
746
747         va_start (args, format);
748         msg = g_strdup_vprintf (format, args);
749         va_end (args);
750         
751         area = ev_message_area_new (GTK_MESSAGE_ERROR,
752                                     msg,
753                                     GTK_STOCK_CLOSE,
754                                     GTK_RESPONSE_CLOSE,
755                                     NULL);
756         g_free (msg);
757         
758         if (error)
759                 ev_message_area_set_secondary_text (EV_MESSAGE_AREA (area), error->message);
760         g_signal_connect (area, "response",
761                           G_CALLBACK (ev_window_message_area_response_cb),
762                           window);
763         gtk_widget_show (area);
764         ev_window_set_message_area (window, area);
765 }
766
767 static void
768 ev_window_warning_message (EvWindow    *window,
769                            const gchar *format,
770                            ...)
771 {
772         GtkWidget *area;
773         va_list    args;
774         gchar     *msg = NULL;
775
776         if (window->priv->message_area)
777                 return;
778
779         va_start (args, format);
780         msg = g_strdup_vprintf (format, args);
781         va_end (args);
782
783         area = ev_message_area_new (GTK_MESSAGE_WARNING,
784                                     msg,
785                                     GTK_STOCK_CLOSE,
786                                     GTK_RESPONSE_CLOSE,
787                                     NULL);
788         g_free (msg);
789         
790         g_signal_connect (area, "response",
791                           G_CALLBACK (ev_window_message_area_response_cb),
792                           window);
793         gtk_widget_show (area);
794         ev_window_set_message_area (window, area);
795 }
796
797 typedef struct _PageTitleData {
798         const gchar *page_label;
799         gchar       *page_title;
800 } PageTitleData;
801
802 static gboolean
803 ev_window_find_page_title (GtkTreeModel  *tree_model,
804                            GtkTreePath   *path,
805                            GtkTreeIter   *iter,
806                            PageTitleData *data)
807 {
808         gchar *page_string;
809         
810         gtk_tree_model_get (tree_model, iter,
811                             EV_DOCUMENT_LINKS_COLUMN_PAGE_LABEL, &page_string, 
812                             -1);
813         
814         if (!page_string)
815                 return FALSE;
816         
817         if (!strcmp (page_string, data->page_label)) {
818                 gtk_tree_model_get (tree_model, iter,
819                                     EV_DOCUMENT_LINKS_COLUMN_MARKUP, &data->page_title, 
820                                     -1);
821                 g_free (page_string);
822                 return TRUE;
823         }
824         
825         g_free (page_string);
826         return FALSE;
827 }
828
829 static gchar *
830 ev_window_get_page_title (EvWindow    *window,
831                           const gchar *page_label)
832 {
833         if (EV_IS_DOCUMENT_LINKS (window->priv->document) &&
834             ev_document_links_has_document_links (EV_DOCUMENT_LINKS (window->priv->document))) {
835                 PageTitleData data;
836                 GtkTreeModel *model;
837
838                 data.page_label = page_label;
839                 data.page_title = NULL;
840
841                 g_object_get (G_OBJECT (window->priv->sidebar_links),
842                               "model", &model,
843                               NULL);
844                 if (model) {
845                         gtk_tree_model_foreach (model,
846                                                 (GtkTreeModelForeachFunc)ev_window_find_page_title,
847                                                 &data);
848
849                         g_object_unref (model);
850                 }
851
852                 return data.page_title;
853         }
854
855         return NULL;
856 }
857
858 static void
859 ev_window_add_history (EvWindow *window, gint page, EvLink *link)
860 {
861         gchar *page_label = NULL;
862         gchar *page_title;
863         gchar *link_title;
864         EvLink *real_link;
865         EvLinkAction *action;
866         EvLinkDest *dest;
867         
868         if (window->priv->history == NULL)
869                 return;
870
871         if (!EV_IS_DOCUMENT_LINKS (window->priv->document))
872                 return;
873         
874         if (link) {
875                 action = g_object_ref (ev_link_get_action (link));
876                 dest = ev_link_action_get_dest (action);
877                 page_label = ev_document_links_get_dest_page_label (EV_DOCUMENT_LINKS (window->priv->document), dest);
878         } else {
879                 dest = ev_link_dest_new_page (page);
880                 action = ev_link_action_new_dest (dest);
881                 page_label = ev_document_get_page_label (window->priv->document, page);
882         }
883
884         if (!page_label)
885                 return;
886
887         page_title = ev_window_get_page_title (window, page_label);
888         if (page_title) {
889                 link_title = g_strdup_printf (_("Page %s — %s"), page_label, page_title);
890                 g_free (page_title);
891         } else {
892                 link_title = g_strdup_printf (_("Page %s"), page_label);
893         }
894
895         real_link = ev_link_new (link_title, action);
896         
897         ev_history_add_link (window->priv->history, real_link);
898
899         g_free (link_title);
900         g_free (page_label);
901         g_object_unref (real_link);
902 }
903
904 static void
905 view_handle_link_cb (EvView *view, EvLink *link, EvWindow *window)
906 {
907         int current_page = ev_document_model_get_page (window->priv->model);
908         
909         ev_window_add_history (window, 0, link);
910         ev_window_add_history (window, current_page, NULL);
911 }
912
913 static void
914 view_selection_changed_cb (EvView   *view,
915                            EvWindow *window)
916 {
917         ev_window_set_action_sensitive (window, "EditCopy",
918                                         ev_view_get_has_selection (view));
919 }
920
921 static void
922 view_layers_changed_cb (EvView   *view,
923                         EvWindow *window)
924 {
925         ev_sidebar_layers_update_layers_state (EV_SIDEBAR_LAYERS (window->priv->sidebar_layers));
926 }
927
928 static void
929 ev_window_page_changed_cb (EvWindow        *ev_window,
930                            gint             old_page,
931                            gint             new_page,
932                            EvDocumentModel *model)
933 {
934         ev_window_update_actions (ev_window);
935
936         ev_window_update_find_status_message (ev_window);
937
938         if (abs (new_page - old_page) > 1) {
939                 ev_window_add_history (ev_window, new_page, NULL);
940                 ev_window_add_history (ev_window, old_page, NULL);
941         }
942
943         if (ev_window->priv->metadata && !ev_window_is_empty (ev_window))
944                 ev_metadata_set_int (ev_window->priv->metadata, "page", new_page);
945 }
946
947 static const gchar *
948 ev_window_sidebar_get_current_page_id (EvWindow *ev_window)
949 {
950         GtkWidget   *current_page;
951         const gchar *id;
952
953         g_object_get (ev_window->priv->sidebar,
954                       "current_page", &current_page,
955                       NULL);
956
957         if (current_page == ev_window->priv->sidebar_links) {
958                 id = LINKS_SIDEBAR_ID;
959         } else if (current_page == ev_window->priv->sidebar_thumbs) {
960                 id = THUMBNAILS_SIDEBAR_ID;
961         } else if (current_page == ev_window->priv->sidebar_attachments) {
962                 id = ATTACHMENTS_SIDEBAR_ID;
963         } else if (current_page == ev_window->priv->sidebar_layers) {
964                 id = LAYERS_SIDEBAR_ID;
965         } else if (current_page == ev_window->priv->sidebar_annots) {
966                 id = ANNOTS_SIDEBAR_ID;
967         } else {
968                 g_assert_not_reached();
969         }
970
971         g_object_unref (current_page);
972
973         return id;
974 }
975
976 static void
977 ev_window_sidebar_set_current_page (EvWindow    *window,
978                                     const gchar *page_id)
979 {
980         EvDocument *document = window->priv->document;
981         EvSidebar  *sidebar = EV_SIDEBAR (window->priv->sidebar);
982         GtkWidget  *links = window->priv->sidebar_links;
983         GtkWidget  *thumbs = window->priv->sidebar_thumbs;
984         GtkWidget  *attachments = window->priv->sidebar_attachments;
985         GtkWidget  *annots = window->priv->sidebar_annots;
986         GtkWidget  *layers = window->priv->sidebar_layers;
987
988         if (strcmp (page_id, LINKS_SIDEBAR_ID) == 0 &&
989             ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (links), document)) {
990                 ev_sidebar_set_page (sidebar, links);
991         } else if (strcmp (page_id, THUMBNAILS_SIDEBAR_ID) == 0 &&
992                    ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (thumbs), document)) {
993                 ev_sidebar_set_page (sidebar, thumbs);
994         } else if (strcmp (page_id, ATTACHMENTS_SIDEBAR_ID) == 0 &&
995                    ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (attachments), document)) {
996                 ev_sidebar_set_page (sidebar, attachments);
997         } else if (strcmp (page_id, LAYERS_SIDEBAR_ID) == 0 &&
998                    ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (layers), document)) {
999                 ev_sidebar_set_page (sidebar, layers);
1000         } else if (strcmp (page_id, ANNOTS_SIDEBAR_ID) == 0 &&
1001                    ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (annots), document)) {
1002                 ev_sidebar_set_page (sidebar, annots);
1003         }
1004 }
1005
1006 static void
1007 update_document_mode (EvWindow *window, EvDocumentMode mode)
1008 {
1009         if (mode == EV_DOCUMENT_MODE_PRESENTATION) {
1010                 ev_window_run_presentation (window);
1011         }
1012         else if (mode == EV_DOCUMENT_MODE_FULL_SCREEN) {
1013                 ev_window_run_fullscreen (window);
1014         }
1015 }
1016
1017 static void
1018 setup_chrome_from_metadata (EvWindow *window)
1019 {
1020         EvChrome chrome = EV_CHROME_NORMAL;
1021         gboolean show_toolbar = TRUE;
1022
1023         if (ev_window_is_empty (window)) {
1024                 window->priv->chrome = chrome;
1025
1026                 return;
1027         }
1028
1029         if (!window->priv->metadata) {
1030                 show_toolbar = g_settings_get_boolean (window->priv->default_settings, "show-toolbar");
1031         } else if (!ev_metadata_get_boolean (window->priv->metadata, "show_toolbar", &show_toolbar)) {
1032                 if (window->priv->is_new_doc)
1033                         show_toolbar = g_settings_get_boolean (window->priv->default_settings, "show-toolbar");
1034         }
1035
1036         if (!show_toolbar)
1037                 chrome &= ~EV_CHROME_TOOLBAR;
1038
1039         window->priv->chrome = chrome;
1040 }
1041
1042 static void
1043 setup_sidebar_from_metadata (EvWindow *window)
1044 {
1045         EvDocument *document = window->priv->document;
1046         GSettings  *settings =  window->priv->default_settings;
1047         gchar      *page_id;
1048         gint        sidebar_size;
1049         gboolean    sidebar_visibility = TRUE;
1050
1051         if (ev_window_is_empty (window))
1052                 return;
1053
1054         if (!window->priv->metadata) {
1055                 sidebar_visibility = g_settings_get_boolean (settings, "show-sidebar");
1056         } else if (!ev_metadata_get_boolean (window->priv->metadata, "sidebar_visibility", &sidebar_visibility)) {
1057                 if (window->priv->is_new_doc)
1058                         sidebar_visibility = g_settings_get_boolean (settings, "show-sidebar");
1059         }
1060
1061         update_chrome_flag (window, EV_CHROME_SIDEBAR, sidebar_visibility);
1062         update_chrome_visibility (window);
1063
1064         if (!window->priv->metadata) {
1065                 /* Set default values */
1066                 gtk_paned_set_position (GTK_PANED (window->priv->hpaned),
1067                                         g_settings_get_int (settings, "sidebar-size"));
1068                 if (document) {
1069                         page_id = g_settings_get_string (settings, "sidebar-page");
1070                         ev_window_sidebar_set_current_page (window, page_id);
1071                         g_free (page_id);
1072                 }
1073
1074                 return;
1075         }
1076
1077         if (ev_metadata_get_int (window->priv->metadata, "sidebar_size", &sidebar_size)) {
1078                 gtk_paned_set_position (GTK_PANED (window->priv->hpaned), sidebar_size);
1079         } else if (window->priv->is_new_doc) {
1080                 gtk_paned_set_position (GTK_PANED (window->priv->hpaned),
1081                                         g_settings_get_int (settings, "sidebar-size"));
1082         }
1083
1084         if (!document)
1085                 return;
1086
1087         if (ev_metadata_get_string (window->priv->metadata, "sidebar_page", &page_id)) {
1088                 ev_window_sidebar_set_current_page (window, page_id);
1089         } else if (window->priv->is_new_doc) {
1090                 page_id = g_settings_get_string (settings, "sidebar-page");
1091                 ev_window_sidebar_set_current_page (window, page_id);
1092                 g_free (page_id);
1093         }
1094 }
1095
1096 static void
1097 setup_model_from_metadata (EvWindow *window)
1098 {
1099         GSettings *settings = window->priv->default_settings;
1100         gint       page;
1101         gchar     *sizing_mode;
1102         gdouble    zoom;
1103         gint       rotation;
1104         gboolean   inverted_colors = FALSE;
1105         gboolean   continuous = FALSE;
1106         gboolean   dual_page = FALSE;
1107         gboolean   fullscreen = FALSE;
1108
1109         if (!window->priv->metadata) {
1110                 /* Set default values */
1111                 ev_document_model_set_sizing_mode (window->priv->model,
1112                                                    g_settings_get_enum (settings, "sizing-mode"));
1113                 ev_document_model_set_inverted_colors (window->priv->model,
1114                                                        g_settings_get_boolean (settings, "inverted-colors"));
1115                 ev_document_model_set_continuous (window->priv->model,
1116                                                   g_settings_get_boolean (settings, "continuous"));
1117                 ev_document_model_set_dual_page (window->priv->model,
1118                                                  g_settings_get_boolean (settings, "dual-page"));
1119                 fullscreen = g_settings_get_boolean (settings, "fullscreen");
1120                 if (fullscreen)
1121                         ev_window_run_fullscreen (window);
1122
1123                 return;
1124         }
1125
1126         /* Current page */
1127         if (!window->priv->dest &&
1128             ev_metadata_get_int (window->priv->metadata, "page", &page)) {
1129                 ev_document_model_set_page (window->priv->model, page);
1130         }
1131
1132         /* Sizing mode */
1133         if (ev_metadata_get_string (window->priv->metadata, "sizing_mode", &sizing_mode)) {
1134                 GEnumValue *enum_value;
1135
1136                 enum_value = g_enum_get_value_by_nick
1137                         (g_type_class_peek (EV_TYPE_SIZING_MODE), sizing_mode);
1138                 ev_document_model_set_sizing_mode (window->priv->model, enum_value->value);
1139         } else if (window->priv->is_new_doc) {
1140                 ev_document_model_set_sizing_mode (window->priv->model,
1141                                                    g_settings_get_enum (settings, "sizing-mode"));
1142         }
1143
1144         /* Zoom */
1145         if (ev_document_model_get_sizing_mode (window->priv->model) == EV_SIZING_FREE &&
1146             ev_metadata_get_double (window->priv->metadata, "zoom", &zoom)) {
1147                 zoom *= get_screen_dpi (window) / 72.0;
1148                 ev_document_model_set_scale (window->priv->model, zoom);
1149         }
1150
1151         /* Rotation */
1152         if (ev_metadata_get_int (window->priv->metadata, "rotation", &rotation)) {
1153                 switch (rotation) {
1154                 case 90:
1155                         rotation = 90;
1156                         break;
1157                 case 180:
1158                         rotation = 180;
1159                         break;
1160                 case 270:
1161                         rotation = 270;
1162                         break;
1163                 default:
1164                         rotation = 0;
1165                         break;
1166                 }
1167                 ev_document_model_set_rotation (window->priv->model, rotation);
1168         }
1169
1170         /* Inverted Colors */
1171         if (ev_metadata_get_boolean (window->priv->metadata, "inverted-colors", &inverted_colors)) {
1172                 ev_document_model_set_inverted_colors (window->priv->model, inverted_colors);
1173         } else if (window->priv->is_new_doc) {
1174                 ev_document_model_set_inverted_colors (window->priv->model,
1175                                                        g_settings_get_boolean (settings, "inverted-colors"));
1176         }
1177
1178         /* Continuous */
1179         if (ev_metadata_get_boolean (window->priv->metadata, "continuous", &continuous)) {
1180                 ev_document_model_set_continuous (window->priv->model, continuous);
1181         } else if (window->priv->is_new_doc) {
1182                 ev_document_model_set_continuous (window->priv->model,
1183                                                   g_settings_get_boolean (settings, "continuous"));
1184         }
1185
1186         /* Dual page */
1187         if (ev_metadata_get_boolean (window->priv->metadata, "dual-page", &dual_page)) {
1188                 ev_document_model_set_dual_page (window->priv->model, dual_page);
1189         } else if (window->priv->is_new_doc) {
1190                 ev_document_model_set_dual_page (window->priv->model,
1191                                                  g_settings_get_boolean (settings, "dual-page"));
1192         }
1193
1194         /* Fullscreen */
1195         if (!ev_metadata_get_boolean (window->priv->metadata, "fullscreen", &fullscreen)) {
1196                 if (window->priv->is_new_doc)
1197                         fullscreen = g_settings_get_boolean (settings, "fullscreen");
1198         }
1199
1200         if (fullscreen)
1201                 ev_window_run_fullscreen (window);
1202 }
1203
1204 static void
1205 setup_document_from_metadata (EvWindow *window)
1206 {
1207         gint    page, n_pages;
1208         gint    width;
1209         gint    height;
1210         gdouble width_ratio;
1211         gdouble height_ratio;
1212
1213         setup_sidebar_from_metadata (window);
1214
1215         if (window->priv->metadata) {
1216                 /* Make sure to not open a document on the last page,
1217                  * since closing it on the last page most likely means the
1218                  * user was finished reading the document. In that case, reopening should
1219                  * show the first page. */
1220                 page = ev_document_model_get_page (window->priv->model);
1221                 n_pages = ev_document_get_n_pages (window->priv->document);
1222                 if (page == n_pages - 1)
1223                         ev_document_model_set_page (window->priv->model, 0);
1224
1225                 if (ev_metadata_get_int (window->priv->metadata, "window_width", &width) &&
1226                     ev_metadata_get_int (window->priv->metadata, "window_height", &height))
1227                         return; /* size was already set in setup_size_from_metadata */
1228         }
1229
1230         g_settings_get (window->priv->default_settings, "window-ratio", "(dd)", &width_ratio, &height_ratio);
1231         if (width_ratio > 0. && height_ratio > 0.) {
1232                 gdouble    document_width;
1233                 gdouble    document_height;
1234                 GdkScreen *screen;
1235                 gint       request_width;
1236                 gint       request_height;
1237
1238                 ev_document_get_max_page_size (window->priv->document,
1239                                                &document_width, &document_height);
1240
1241                 request_width = (gint)(width_ratio * document_width + 0.5);
1242                 request_height = (gint)(height_ratio * document_height + 0.5);
1243
1244                 screen = gtk_window_get_screen (GTK_WINDOW (window));
1245                 if (screen) {
1246                         request_width = MIN (request_width, gdk_screen_get_width (screen));
1247                         request_height = MIN (request_height, gdk_screen_get_height (screen));
1248                 }
1249
1250                 if (request_width > 0 && request_height > 0) {
1251                         gtk_window_resize (GTK_WINDOW (window),
1252                                            request_width,
1253                                            request_height);
1254                 }
1255         }
1256 }
1257
1258 static void
1259 setup_size_from_metadata (EvWindow *window)
1260 {
1261         gint     width;
1262         gint     height;
1263         gboolean maximized;
1264         gint     x;
1265         gint     y;
1266
1267         if (!window->priv->metadata)
1268                 return;
1269
1270         if (ev_metadata_get_boolean (window->priv->metadata, "window_maximized", &maximized)) {
1271                 if (maximized) {
1272                         gtk_window_maximize (GTK_WINDOW (window));
1273                         return;
1274                 } else {
1275                         gtk_window_unmaximize (GTK_WINDOW (window));
1276                 }
1277         }
1278
1279         if (ev_metadata_get_int (window->priv->metadata, "window_x", &x) &&
1280             ev_metadata_get_int (window->priv->metadata, "window_y", &y)) {
1281                 gtk_window_move (GTK_WINDOW (window), x, y);
1282         }
1283
1284         if (ev_metadata_get_int (window->priv->metadata, "window_width", &width) &&
1285             ev_metadata_get_int (window->priv->metadata, "window_height", &height)) {
1286                 gtk_window_resize (GTK_WINDOW (window), width, height);
1287         }
1288 }
1289
1290 static void
1291 setup_view_from_metadata (EvWindow *window)
1292 {
1293         gboolean presentation;
1294
1295         if (!window->priv->metadata)
1296                 return;
1297
1298         /* Presentation */
1299         if (ev_metadata_get_boolean (window->priv->metadata, "presentation", &presentation)) {
1300                 if (presentation) {
1301                         ev_window_run_presentation (window);
1302                 }
1303         }
1304 }
1305
1306 static void
1307 ev_window_clear_thumbnail_job (EvWindow *ev_window)
1308 {
1309         if (ev_window->priv->thumbnail_job != NULL) {
1310                 if (!ev_job_is_finished (ev_window->priv->thumbnail_job))
1311                         ev_job_cancel (ev_window->priv->thumbnail_job);
1312                 
1313                 g_signal_handlers_disconnect_by_func (ev_window->priv->thumbnail_job,
1314                                                       ev_window_set_icon_from_thumbnail,
1315                                                       ev_window);
1316                 g_object_unref (ev_window->priv->thumbnail_job);
1317                 ev_window->priv->thumbnail_job = NULL;
1318         }
1319 }
1320
1321 static void
1322 ev_window_set_icon_from_thumbnail (EvJobThumbnail *job,
1323                                    EvWindow       *ev_window)
1324 {
1325         if (job->thumbnail) {
1326                 if (ev_document_model_get_inverted_colors (ev_window->priv->model))
1327                         ev_document_misc_invert_pixbuf (job->thumbnail);
1328                 gtk_window_set_icon (GTK_WINDOW (ev_window),
1329                                      job->thumbnail);
1330         }
1331
1332         ev_window_clear_thumbnail_job (ev_window);
1333 }
1334
1335 static void
1336 ev_window_refresh_window_thumbnail (EvWindow *ev_window)
1337 {
1338         gdouble page_width;
1339         gdouble scale;
1340         gint rotation;
1341         EvDocument *document = ev_window->priv->document;
1342
1343         if (ev_document_get_n_pages (document) <= 0 ||
1344             !ev_document_check_dimensions (document)) {
1345                 return;
1346         }
1347
1348         ev_window_clear_thumbnail_job (ev_window);
1349
1350         ev_document_get_page_size (document, 0, &page_width, NULL);
1351         scale = 128. / page_width;
1352         rotation = ev_document_model_get_rotation (ev_window->priv->model);
1353
1354         ev_window->priv->thumbnail_job = ev_job_thumbnail_new (document, 0, rotation, scale);
1355         g_signal_connect (ev_window->priv->thumbnail_job, "finished",
1356                           G_CALLBACK (ev_window_set_icon_from_thumbnail),
1357                           ev_window);
1358         ev_job_scheduler_push_job (ev_window->priv->thumbnail_job, EV_JOB_PRIORITY_NONE);
1359 }
1360
1361 static void
1362 override_restrictions_changed (GSettings *settings,
1363                                gchar     *key,
1364                                EvWindow  *ev_window)
1365 {
1366         ev_window_setup_action_sensitivity (ev_window);
1367 }
1368
1369 static void
1370 lockdown_changed (GSettings   *lockdown,
1371                   const gchar *key,
1372                   EvWindow    *ev_window)
1373 {
1374         ev_window_setup_action_sensitivity (ev_window);
1375 }
1376
1377 static gboolean
1378 ev_window_setup_document (EvWindow *ev_window)
1379 {
1380         const EvDocumentInfo *info;
1381         EvDocument *document = ev_window->priv->document;
1382         GtkAction *action;
1383
1384         ev_window->priv->setup_document_idle = 0;
1385
1386         ev_window_refresh_window_thumbnail (ev_window);
1387
1388         ev_window_set_page_mode (ev_window, PAGE_MODE_DOCUMENT);
1389         ev_window_title_set_document (ev_window->priv->title, document);
1390         ev_window_title_set_uri (ev_window->priv->title, ev_window->priv->uri);
1391
1392         if (!ev_window->priv->settings) {
1393                 ev_window->priv->settings = g_settings_new (GS_SCHEMA_NAME);
1394                 g_signal_connect (ev_window->priv->settings,
1395                                   "changed::"GS_OVERRIDE_RESTRICTIONS,
1396                                   G_CALLBACK (override_restrictions_changed),
1397                                   ev_window);
1398         }
1399
1400 #ifdef HAVE_DESKTOP_SCHEMAS
1401         if (!ev_window->priv->lockdown_settings) {
1402                 ev_window->priv->lockdown_settings = g_settings_new (GS_LOCKDOWN_SCHEMA_NAME);
1403                 g_signal_connect (ev_window->priv->lockdown_settings,
1404                                   "changed",
1405                                   G_CALLBACK (lockdown_changed),
1406                                   ev_window);
1407         }
1408 #endif
1409
1410         ev_window_setup_action_sensitivity (ev_window);
1411
1412         if (ev_window->priv->history)
1413                 g_object_unref (ev_window->priv->history);
1414         ev_window->priv->history = ev_history_new ();
1415         action = gtk_action_group_get_action (ev_window->priv->action_group, NAVIGATION_ACTION);
1416         ev_navigation_action_set_history (EV_NAVIGATION_ACTION (action), ev_window->priv->history);
1417         
1418         if (ev_window->priv->properties) {
1419                 ev_properties_dialog_set_document (EV_PROPERTIES_DIALOG (ev_window->priv->properties),
1420                                                    ev_window->priv->uri,
1421                                                    ev_window->priv->document);
1422         }
1423         
1424         info = ev_document_get_info (document);
1425         update_document_mode (ev_window, info->mode);
1426
1427         if (EV_WINDOW_IS_PRESENTATION (ev_window))
1428                 gtk_widget_grab_focus (ev_window->priv->presentation_view);
1429         else
1430                 gtk_widget_grab_focus (ev_window->priv->view);
1431
1432         return FALSE;
1433 }
1434
1435 static void
1436 ev_window_set_document (EvWindow *ev_window, EvDocument *document)
1437 {
1438         if (ev_window->priv->document == document)
1439                 return;
1440
1441         if (ev_window->priv->document)
1442                 g_object_unref (ev_window->priv->document);
1443         ev_window->priv->document = g_object_ref (document);
1444
1445         ev_window_update_max_min_scale (ev_window);
1446
1447         ev_window_set_message_area (ev_window, NULL);
1448
1449         if (ev_document_get_n_pages (document) <= 0) {
1450                 ev_window_warning_message (ev_window, "%s",
1451                                            _("The document contains no pages"));
1452         } else if (!ev_document_check_dimensions (document)) {
1453                 ev_window_warning_message (ev_window, "%s",
1454                                            _("The document contains only empty pages"));
1455         }
1456
1457         if (EV_WINDOW_IS_PRESENTATION (ev_window)) {
1458                 gtk_widget_destroy (ev_window->priv->presentation_view);
1459                 ev_window->priv->presentation_view = NULL;
1460                 ev_window_run_presentation (ev_window);
1461         }
1462
1463         if (ev_window->priv->setup_document_idle > 0)
1464                 g_source_remove (ev_window->priv->setup_document_idle);
1465
1466         ev_window->priv->setup_document_idle = g_idle_add ((GSourceFunc)ev_window_setup_document, ev_window);
1467 }
1468
1469 static void
1470 ev_window_document_changed (EvWindow *ev_window,
1471                             gpointer  user_data)
1472 {
1473         ev_window_reload_document (ev_window, NULL);
1474 }
1475
1476 static void
1477 ev_window_password_view_unlock (EvWindow *ev_window)
1478 {
1479         const gchar *password;
1480         
1481         g_assert (ev_window->priv->load_job);
1482
1483         password = ev_password_view_get_password (EV_PASSWORD_VIEW (ev_window->priv->password_view));
1484         ev_job_load_set_password (EV_JOB_LOAD (ev_window->priv->load_job), password);
1485         ev_job_scheduler_push_job (ev_window->priv->load_job, EV_JOB_PRIORITY_NONE);
1486 }
1487
1488 static void
1489 ev_window_clear_load_job (EvWindow *ev_window)
1490 {
1491         if (ev_window->priv->load_job != NULL) {
1492                 if (!ev_job_is_finished (ev_window->priv->load_job))
1493                         ev_job_cancel (ev_window->priv->load_job);
1494                 
1495                 g_signal_handlers_disconnect_by_func (ev_window->priv->load_job, ev_window_load_job_cb, ev_window);
1496                 g_object_unref (ev_window->priv->load_job);
1497                 ev_window->priv->load_job = NULL;
1498         }
1499 }
1500
1501 static void
1502 ev_window_clear_reload_job (EvWindow *ev_window)
1503 {
1504         if (ev_window->priv->reload_job != NULL) {
1505                 if (!ev_job_is_finished (ev_window->priv->reload_job))
1506                         ev_job_cancel (ev_window->priv->reload_job);
1507                 
1508                 g_signal_handlers_disconnect_by_func (ev_window->priv->reload_job, ev_window_reload_job_cb, ev_window);
1509                 g_object_unref (ev_window->priv->reload_job);
1510                 ev_window->priv->reload_job = NULL;
1511         }
1512 }
1513
1514 static void
1515 ev_window_clear_local_uri (EvWindow *ev_window)
1516 {
1517         if (ev_window->priv->local_uri) {
1518                 ev_tmp_uri_unlink (ev_window->priv->local_uri);
1519                 g_free (ev_window->priv->local_uri);
1520                 ev_window->priv->local_uri = NULL;
1521         }
1522 }
1523
1524 static void
1525 ev_window_handle_link (EvWindow *ev_window,
1526                        EvLinkDest *dest)
1527 {
1528         if (dest) {
1529                 EvLink *link;
1530                 EvLinkAction *link_action;
1531
1532                 link_action = ev_link_action_new_dest (dest);
1533                 link = ev_link_new (NULL, link_action);
1534                 ev_view_handle_link (EV_VIEW (ev_window->priv->view), link);
1535                 g_object_unref (link);
1536         }
1537 }
1538
1539 /* This callback will executed when load job will be finished.
1540  *
1541  * Since the flow of the error dialog is very confusing, we assume that both
1542  * document and uri will go away after this function is called, and thus we need
1543  * to ref/dup them.  Additionally, it needs to clear
1544  * ev_window->priv->password_{uri,document}, and thus people who call this
1545  * function should _not_ necessarily expect those to exist after being
1546  * called. */
1547 static void
1548 ev_window_load_job_cb (EvJob *job,
1549                        gpointer data)
1550 {
1551         EvWindow *ev_window = EV_WINDOW (data);
1552         EvDocument *document = EV_JOB (job)->document;
1553         EvJobLoad *job_load = EV_JOB_LOAD (job);
1554
1555         g_assert (job_load->uri);
1556
1557         ev_view_set_loading (EV_VIEW (ev_window->priv->view), FALSE);
1558
1559         /* Success! */
1560         if (!ev_job_is_failed (job)) {
1561                 ev_document_model_set_document (ev_window->priv->model, document);
1562
1563 #ifdef ENABLE_DBUS
1564                 ev_window_emit_doc_loaded (ev_window);
1565 #endif
1566                 setup_chrome_from_metadata (ev_window);
1567                 update_chrome_actions (ev_window);
1568                 setup_document_from_metadata (ev_window);
1569                 setup_view_from_metadata (ev_window);
1570
1571                 ev_window_add_recent (ev_window, ev_window->priv->uri);
1572
1573                 ev_window_title_set_type (ev_window->priv->title,
1574                                           EV_WINDOW_TITLE_DOCUMENT);
1575                 if (job_load->password) {
1576                         GPasswordSave flags;
1577
1578                         flags = ev_password_view_get_password_save_flags (
1579                                 EV_PASSWORD_VIEW (ev_window->priv->password_view));
1580                         ev_keyring_save_password (ev_window->priv->uri,
1581                                                   job_load->password,
1582                                                   flags);
1583                 }
1584
1585                 ev_window_handle_link (ev_window, ev_window->priv->dest);
1586                 /* Already unrefed by ev_link_action
1587                  * FIXME: link action should inc dest ref counting
1588                  * or not unref it at all
1589                  */
1590                 ev_window->priv->dest = NULL;
1591
1592                 switch (ev_window->priv->window_mode) {
1593                         case EV_WINDOW_MODE_FULLSCREEN:
1594                                 ev_window_run_fullscreen (ev_window);
1595                                 break;
1596                         case EV_WINDOW_MODE_PRESENTATION:
1597                                 ev_window_run_presentation (ev_window);
1598                                 break;
1599                         default:
1600                                 break;
1601                 }
1602
1603                 if (ev_window->priv->search_string && EV_IS_DOCUMENT_FIND (document)) {
1604                         ev_window_cmd_edit_find (NULL, ev_window);
1605                         egg_find_bar_set_search_string (EGG_FIND_BAR (ev_window->priv->find_bar),
1606                                                         ev_window->priv->search_string);
1607                 }
1608
1609                 g_free (ev_window->priv->search_string);
1610                 ev_window->priv->search_string = NULL;
1611
1612                 /* Create a monitor for the document */
1613                 ev_window->priv->monitor = ev_file_monitor_new (ev_window->priv->uri);
1614                 g_signal_connect_swapped (ev_window->priv->monitor, "changed",
1615                                           G_CALLBACK (ev_window_document_changed),
1616                                           ev_window);
1617                 
1618                 ev_window_clear_load_job (ev_window);
1619                 return;
1620         }
1621
1622         if (g_error_matches (job->error, EV_DOCUMENT_ERROR, EV_DOCUMENT_ERROR_ENCRYPTED)) {
1623                 gchar *password;
1624                 
1625                 setup_view_from_metadata (ev_window);
1626                 
1627                 /* First look whether password is in keyring */
1628                 password = ev_keyring_lookup_password (ev_window->priv->uri);
1629                 if (password) {
1630                         if (job_load->password && strcmp (password, job_load->password) == 0) {
1631                                 /* Password in kering is wrong */
1632                                 ev_job_load_set_password (job_load, NULL);
1633                                 /* FIXME: delete password from keyring? */
1634                         } else {
1635                                 ev_job_load_set_password (job_load, password);
1636                                 ev_job_scheduler_push_job (job, EV_JOB_PRIORITY_NONE);
1637                                 g_free (password);
1638                                 return;
1639                         }
1640
1641                         g_free (password);
1642                 }
1643
1644                 /* We need to ask the user for a password */
1645                 ev_window_title_set_uri (ev_window->priv->title,
1646                                          ev_window->priv->uri);
1647                 ev_window_title_set_type (ev_window->priv->title,
1648                                           EV_WINDOW_TITLE_PASSWORD);
1649
1650                 ev_password_view_set_uri (EV_PASSWORD_VIEW (ev_window->priv->password_view),
1651                                           job_load->uri);
1652
1653                 ev_window_set_page_mode (ev_window, PAGE_MODE_PASSWORD);
1654
1655                 ev_job_load_set_password (job_load, NULL);
1656                 ev_password_view_ask_password (EV_PASSWORD_VIEW (ev_window->priv->password_view));
1657         } else {
1658                 ev_window_error_message (ev_window, job->error, 
1659                                          "%s", _("Unable to open document"));
1660                 ev_window_clear_load_job (ev_window);
1661         }       
1662 }
1663
1664 static void
1665 ev_window_reload_job_cb (EvJob    *job,
1666                          EvWindow *ev_window)
1667 {
1668         GtkWidget *widget;
1669
1670         if (ev_job_is_failed (job)) {
1671                 ev_window_clear_reload_job (ev_window);
1672                 ev_window->priv->in_reload = FALSE;
1673                 if (ev_window->priv->dest) {
1674                         g_object_unref (ev_window->priv->dest);
1675                         ev_window->priv->dest = NULL;
1676                 }
1677
1678                 return;
1679         }
1680
1681         ev_document_model_set_document (ev_window->priv->model,
1682                                         job->document);
1683         if (ev_window->priv->dest) {
1684                 ev_window_handle_link (ev_window, ev_window->priv->dest);
1685                 /* Already unrefed by ev_link_action
1686                  * FIXME: link action should inc dest ref counting
1687                  * or not unref it at all
1688                  */
1689                 ev_window->priv->dest = NULL;
1690         }
1691
1692         /* Restart the search after reloading */
1693         widget = gtk_window_get_focus (GTK_WINDOW (ev_window));
1694         if (widget && gtk_widget_get_ancestor (widget, EGG_TYPE_FIND_BAR)) {
1695                 find_bar_search_changed_cb (EGG_FIND_BAR (ev_window->priv->find_bar),
1696                                             NULL, ev_window);
1697         }
1698         
1699         ev_window_clear_reload_job (ev_window);
1700         ev_window->priv->in_reload = FALSE;
1701 }
1702
1703 /**
1704  * ev_window_get_uri:
1705  * @ev_window: The instance of the #EvWindow.
1706  *
1707  * It returns the uri of the document showed in the #EvWindow.
1708  *
1709  * Returns: the uri of the document showed in the #EvWindow.
1710  */
1711 const char *
1712 ev_window_get_uri (EvWindow *ev_window)
1713 {
1714         return ev_window->priv->uri;
1715 }
1716
1717 /**
1718  * ev_window_close_dialogs:
1719  * @ev_window: The window where dialogs will be closed.
1720  *
1721  * It looks for password, print and properties dialogs and closes them and
1722  * frees them from memory. If there is any print job it does free it too.
1723  */
1724 static void
1725 ev_window_close_dialogs (EvWindow *ev_window)
1726 {
1727         if (ev_window->priv->print_dialog)
1728                 gtk_widget_destroy (ev_window->priv->print_dialog);
1729         ev_window->priv->print_dialog = NULL;
1730         
1731         if (ev_window->priv->properties)
1732                 gtk_widget_destroy (ev_window->priv->properties);
1733         ev_window->priv->properties = NULL;
1734 }
1735
1736 static void
1737 ev_window_clear_progress_idle (EvWindow *ev_window)
1738 {
1739         if (ev_window->priv->progress_idle > 0)
1740                 g_source_remove (ev_window->priv->progress_idle);
1741         ev_window->priv->progress_idle = 0;
1742 }
1743
1744 static void
1745 reset_progress_idle (EvWindow *ev_window)
1746 {
1747         ev_window->priv->progress_idle = 0;
1748 }
1749
1750 static void
1751 ev_window_show_progress_message (EvWindow   *ev_window,
1752                                  guint       interval,
1753                                  GSourceFunc function)
1754 {
1755         if (ev_window->priv->progress_idle > 0)
1756                 g_source_remove (ev_window->priv->progress_idle);
1757         ev_window->priv->progress_idle =
1758                 g_timeout_add_seconds_full (G_PRIORITY_DEFAULT,
1759                                             interval, function,
1760                                             ev_window,
1761                                             (GDestroyNotify)reset_progress_idle);
1762 }
1763
1764 static void
1765 ev_window_reset_progress_cancellable (EvWindow *ev_window)
1766 {
1767         if (ev_window->priv->progress_cancellable)
1768                 g_cancellable_reset (ev_window->priv->progress_cancellable);
1769         else
1770                 ev_window->priv->progress_cancellable = g_cancellable_new ();
1771 }
1772
1773 static void
1774 ev_window_progress_response_cb (EvProgressMessageArea *area,
1775                                 gint                   response,
1776                                 EvWindow              *ev_window)
1777 {
1778         if (response == GTK_RESPONSE_CANCEL)
1779                 g_cancellable_cancel (ev_window->priv->progress_cancellable);
1780         ev_window_set_message_area (ev_window, NULL);
1781 }
1782
1783 static gboolean 
1784 show_loading_progress (EvWindow *ev_window)
1785 {
1786         GtkWidget *area;
1787         gchar     *text;
1788         gchar     *display_name;
1789         
1790         if (ev_window->priv->message_area)
1791                 return FALSE;
1792
1793         text = g_uri_unescape_string (ev_window->priv->uri, NULL);
1794         display_name = g_markup_escape_text (text, -1);
1795         g_free (text);
1796         text = g_strdup_printf (_("Loading document from “%s”"),
1797                                 display_name);
1798
1799         area = ev_progress_message_area_new (GTK_STOCK_OPEN,
1800                                              text,
1801                                              GTK_STOCK_CLOSE,
1802                                              GTK_RESPONSE_CLOSE,
1803                                              GTK_STOCK_CANCEL,
1804                                              GTK_RESPONSE_CANCEL,
1805                                              NULL);
1806         g_signal_connect (area, "response",
1807                           G_CALLBACK (ev_window_progress_response_cb),
1808                           ev_window);
1809         gtk_widget_show (area);
1810         ev_window_set_message_area (ev_window, area);
1811
1812         g_free (text);
1813         g_free (display_name);
1814
1815         return FALSE;
1816 }
1817
1818 static void
1819 ev_window_load_remote_failed (EvWindow *ev_window,
1820                               GError   *error)
1821 {
1822         ev_view_set_loading (EV_VIEW (ev_window->priv->view), FALSE);
1823         ev_window->priv->in_reload = FALSE;
1824         ev_window_error_message (ev_window, error, 
1825                                  "%s", _("Unable to open document"));
1826         g_free (ev_window->priv->local_uri);
1827         ev_window->priv->local_uri = NULL;
1828         ev_window->priv->uri_mtime = 0;
1829 }
1830
1831 static void
1832 set_uri_mtime (GFile        *source,
1833                GAsyncResult *async_result,
1834                EvWindow     *ev_window)
1835 {
1836         GFileInfo *info;
1837         GError *error = NULL;
1838
1839         info = g_file_query_info_finish (source, async_result, &error);
1840
1841         if (error) {
1842                 ev_window->priv->uri_mtime = 0;
1843                 g_error_free (error);
1844         } else {
1845                 GTimeVal mtime;
1846                 
1847                 g_file_info_get_modification_time (info, &mtime);
1848                 ev_window->priv->uri_mtime = mtime.tv_sec;
1849                 g_object_unref (info);
1850         }
1851
1852         g_object_unref (source);
1853 }
1854
1855 static void
1856 mount_volume_ready_cb (GFile        *source,
1857                        GAsyncResult *async_result,
1858                        EvWindow     *ev_window)
1859 {
1860         GError *error = NULL;
1861
1862         g_file_mount_enclosing_volume_finish (source, async_result, &error);
1863
1864         if (error) {
1865                 ev_window_load_remote_failed (ev_window, error);
1866                 g_object_unref (source);
1867                 g_error_free (error);
1868         } else {
1869                 /* Volume successfully mounted,
1870                    try opening the file again */
1871                 ev_window_load_file_remote (ev_window, source);
1872         }
1873 }
1874
1875 static void
1876 window_open_file_copy_ready_cb (GFile        *source,
1877                                 GAsyncResult *async_result,
1878                                 EvWindow     *ev_window)
1879 {
1880         GError *error = NULL;
1881
1882         ev_window_clear_progress_idle (ev_window);
1883         ev_window_set_message_area (ev_window, NULL);
1884
1885         g_file_copy_finish (source, async_result, &error);
1886         if (!error) {
1887                 ev_job_scheduler_push_job (ev_window->priv->load_job, EV_JOB_PRIORITY_NONE);
1888                 g_file_query_info_async (source,
1889                                          G_FILE_ATTRIBUTE_TIME_MODIFIED,
1890                                          0, G_PRIORITY_DEFAULT,
1891                                          NULL,
1892                                          (GAsyncReadyCallback)set_uri_mtime,
1893                                          ev_window);
1894                 return;
1895         }
1896
1897         if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_MOUNTED)) {
1898                 GMountOperation *operation;
1899
1900                 operation = gtk_mount_operation_new (GTK_WINDOW (ev_window));
1901                 g_file_mount_enclosing_volume (source,
1902                                                G_MOUNT_MOUNT_NONE,
1903                                                operation, NULL,
1904                                                (GAsyncReadyCallback)mount_volume_ready_cb,
1905                                                ev_window);
1906                 g_object_unref (operation);
1907         } else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
1908                 ev_window_clear_load_job (ev_window);
1909                 ev_window_clear_local_uri (ev_window);
1910                 g_free (ev_window->priv->uri);
1911                 ev_window->priv->uri = NULL;
1912                 g_object_unref (source);
1913                 
1914                 ev_view_set_loading (EV_VIEW (ev_window->priv->view), FALSE);
1915         } else {
1916                 ev_window_load_remote_failed (ev_window, error);
1917                 g_object_unref (source);
1918         }
1919         
1920         g_error_free (error);
1921 }
1922
1923 static void
1924 window_open_file_copy_progress_cb (goffset   n_bytes,
1925                                    goffset   total_bytes,
1926                                    EvWindow *ev_window)
1927 {
1928         gchar *status;
1929         gdouble fraction;
1930         
1931         if (!ev_window->priv->message_area)
1932                 return;
1933
1934         if (total_bytes <= 0)
1935                 return;
1936
1937         fraction = n_bytes / (gdouble)total_bytes;
1938         status = g_strdup_printf (_("Downloading document (%d%%)"),
1939                                   (gint)(fraction * 100));
1940         
1941         ev_progress_message_area_set_status (EV_PROGRESS_MESSAGE_AREA (ev_window->priv->message_area),
1942                                              status);
1943         ev_progress_message_area_set_fraction (EV_PROGRESS_MESSAGE_AREA (ev_window->priv->message_area),
1944                                                fraction);
1945
1946         g_free (status);
1947 }
1948
1949 static void
1950 ev_window_load_file_remote (EvWindow *ev_window,
1951                             GFile    *source_file)
1952 {
1953         GFile *target_file;
1954         
1955         if (!ev_window->priv->local_uri) {
1956                 char *base_name, *template;
1957                 GFile *tmp_file;
1958                 GError *err = NULL;
1959
1960                 /* We'd like to keep extension of source uri since
1961                  * it helps to resolve some mime types, say cbz.
1962                  */
1963                 base_name = g_file_get_basename (source_file);
1964                 template = g_strdup_printf ("document.XXXXXX-%s", base_name);
1965                 g_free (base_name);
1966
1967                 tmp_file = ev_mkstemp_file (template, &err);
1968                 g_free (template);
1969                 if (tmp_file == NULL) {
1970                         ev_window_error_message (ev_window, err,
1971                                                  "%s", _("Failed to load remote file."));
1972                         g_error_free (err);
1973                         return;
1974                 }
1975
1976                 ev_window->priv->local_uri = g_file_get_uri (tmp_file);
1977                 g_object_unref (tmp_file);
1978
1979                 ev_job_load_set_uri (EV_JOB_LOAD (ev_window->priv->load_job),
1980                                      ev_window->priv->local_uri);
1981         }
1982
1983         ev_window_reset_progress_cancellable (ev_window);
1984         
1985         target_file = g_file_new_for_uri (ev_window->priv->local_uri);
1986         g_file_copy_async (source_file, target_file,
1987                            G_FILE_COPY_OVERWRITE,
1988                            G_PRIORITY_DEFAULT,
1989                            ev_window->priv->progress_cancellable,
1990                            (GFileProgressCallback)window_open_file_copy_progress_cb,
1991                            ev_window, 
1992                            (GAsyncReadyCallback)window_open_file_copy_ready_cb,
1993                            ev_window);
1994         g_object_unref (target_file);
1995
1996         ev_window_show_progress_message (ev_window, 1,
1997                                          (GSourceFunc)show_loading_progress);
1998 }
1999
2000 void
2001 ev_window_open_uri (EvWindow       *ev_window,
2002                     const char     *uri,
2003                     EvLinkDest     *dest,
2004                     EvWindowRunMode mode,
2005                     const gchar    *search_string)
2006 {
2007         GFile *source_file;
2008
2009         ev_window->priv->in_reload = FALSE;
2010         
2011         if (ev_window->priv->uri &&
2012             g_ascii_strcasecmp (ev_window->priv->uri, uri) == 0) {
2013                 ev_window_reload_document (ev_window, dest);
2014                 return;
2015         }
2016
2017         if (ev_window->priv->monitor) {
2018                 g_object_unref (ev_window->priv->monitor);
2019                 ev_window->priv->monitor = NULL;
2020         }
2021         
2022         ev_window_close_dialogs (ev_window);
2023         ev_window_clear_load_job (ev_window);
2024         ev_window_clear_local_uri (ev_window);
2025
2026         ev_window->priv->window_mode = mode;
2027
2028         if (ev_window->priv->uri)
2029                 g_free (ev_window->priv->uri);
2030         ev_window->priv->uri = g_strdup (uri);
2031
2032         if (ev_window->priv->metadata)
2033                 g_object_unref (ev_window->priv->metadata);
2034         if (ev_window->priv->bookmarks)
2035                 g_object_unref (ev_window->priv->bookmarks);
2036
2037         source_file = g_file_new_for_uri (uri);
2038         if (!ev_file_is_temp (source_file) && ev_is_metadata_supported_for_file (source_file)) {
2039                 ev_window->priv->metadata = ev_metadata_new (source_file);
2040                 ev_window->priv->is_new_doc = ev_metadata_is_empty (ev_window->priv->metadata);
2041         } else {
2042                 ev_window->priv->metadata = NULL;
2043         }
2044
2045         if (ev_window->priv->metadata) {
2046                 ev_window->priv->bookmarks = ev_bookmarks_new (ev_window->priv->metadata);
2047                 g_signal_connect_swapped (ev_window->priv->bookmarks, "changed",
2048                                           G_CALLBACK (ev_window_setup_bookmarks),
2049                                           ev_window);
2050         } else {
2051                 ev_window->priv->bookmarks = NULL;
2052         }
2053
2054         if (ev_window->priv->search_string)
2055                 g_free (ev_window->priv->search_string);
2056         ev_window->priv->search_string = search_string ?
2057                 g_strdup (search_string) : NULL;
2058
2059         if (ev_window->priv->dest)
2060                 g_object_unref (ev_window->priv->dest);
2061         ev_window->priv->dest = dest ? g_object_ref (dest) : NULL;
2062
2063         setup_size_from_metadata (ev_window);
2064         setup_model_from_metadata (ev_window);
2065         ev_window_setup_bookmarks (ev_window);
2066
2067         ev_window->priv->load_job = ev_job_load_new (uri);
2068         g_signal_connect (ev_window->priv->load_job,
2069                           "finished",
2070                           G_CALLBACK (ev_window_load_job_cb),
2071                           ev_window);
2072
2073         if (!g_file_is_native (source_file) && !ev_window->priv->local_uri) {
2074                 ev_window_load_file_remote (ev_window, source_file);
2075         } else {
2076                 ev_view_set_loading (EV_VIEW (ev_window->priv->view), TRUE);
2077                 g_object_unref (source_file);
2078                 ev_job_scheduler_push_job (ev_window->priv->load_job, EV_JOB_PRIORITY_NONE);
2079         }
2080 }
2081
2082 void
2083 ev_window_open_document (EvWindow       *ev_window,
2084                          EvDocument     *document,
2085                          EvLinkDest     *dest,
2086                          EvWindowRunMode mode,
2087                          const gchar    *search_string)
2088 {
2089         if (document == ev_window->priv->document)
2090                 return;
2091
2092         ev_window_close_dialogs (ev_window);
2093         ev_window_clear_load_job (ev_window);
2094         ev_window_clear_local_uri (ev_window);
2095
2096         if (ev_window->priv->monitor) {
2097                 g_object_unref (ev_window->priv->monitor);
2098                 ev_window->priv->monitor = NULL;
2099         }
2100
2101         if (ev_window->priv->uri)
2102                 g_free (ev_window->priv->uri);
2103         ev_window->priv->uri = g_strdup (ev_document_get_uri (document));
2104
2105         setup_size_from_metadata (ev_window);
2106         setup_model_from_metadata (ev_window);
2107
2108         ev_document_model_set_document (ev_window->priv->model, document);
2109
2110         setup_document_from_metadata (ev_window);
2111         setup_view_from_metadata (ev_window);
2112
2113         if (dest) {
2114                 EvLink *link;
2115                 EvLinkAction *link_action;
2116
2117                 link_action = ev_link_action_new_dest (dest);
2118                 link = ev_link_new (NULL, link_action);
2119                 ev_view_handle_link (EV_VIEW (ev_window->priv->view), link);
2120                 /* FIXME: link action should inc dest ref counting
2121                  * or not unref it at all
2122                  */
2123                 g_object_ref (dest);
2124                 g_object_unref (link);
2125         }
2126
2127         switch (mode) {
2128         case EV_WINDOW_MODE_FULLSCREEN:
2129                 ev_window_run_fullscreen (ev_window);
2130                 break;
2131         case EV_WINDOW_MODE_PRESENTATION:
2132                 ev_window_run_presentation (ev_window);
2133                 break;
2134         default:
2135                 break;
2136         }
2137
2138         if (search_string && EV_IS_DOCUMENT_FIND (document)) {
2139                 ev_window_cmd_edit_find (NULL, ev_window);
2140                 egg_find_bar_set_search_string (EGG_FIND_BAR (ev_window->priv->find_bar),
2141                                                 search_string);
2142         }
2143
2144         /* Create a monitor for the document */
2145         ev_window->priv->monitor = ev_file_monitor_new (ev_window->priv->uri);
2146         g_signal_connect_swapped (ev_window->priv->monitor, "changed",
2147                                   G_CALLBACK (ev_window_document_changed),
2148                                   ev_window);
2149 }
2150
2151 static void
2152 ev_window_reload_local (EvWindow *ev_window)
2153 {
2154         const gchar *uri;
2155         
2156         uri = ev_window->priv->local_uri ? ev_window->priv->local_uri : ev_window->priv->uri;
2157         ev_window->priv->reload_job = ev_job_load_new (uri);
2158         g_signal_connect (ev_window->priv->reload_job, "finished",
2159                           G_CALLBACK (ev_window_reload_job_cb),
2160                           ev_window);
2161         ev_job_scheduler_push_job (ev_window->priv->reload_job, EV_JOB_PRIORITY_NONE);
2162 }
2163
2164 static gboolean 
2165 show_reloading_progress (EvWindow *ev_window)
2166 {
2167         GtkWidget *area;
2168         gchar     *text;
2169         
2170         if (ev_window->priv->message_area)
2171                 return FALSE;
2172         
2173         text = g_strdup_printf (_("Reloading document from %s"),
2174                                 ev_window->priv->uri);
2175         area = ev_progress_message_area_new (GTK_STOCK_REFRESH,
2176                                              text,
2177                                              GTK_STOCK_CLOSE,
2178                                              GTK_RESPONSE_CLOSE,
2179                                              GTK_STOCK_CANCEL,
2180                                              GTK_RESPONSE_CANCEL,
2181                                              NULL);
2182         g_signal_connect (area, "response",
2183                           G_CALLBACK (ev_window_progress_response_cb),
2184                           ev_window);
2185         gtk_widget_show (area);
2186         ev_window_set_message_area (ev_window, area);
2187         g_free (text);
2188
2189         return FALSE;
2190 }
2191
2192 static void
2193 reload_remote_copy_ready_cb (GFile        *remote,
2194                              GAsyncResult *async_result,
2195                              EvWindow     *ev_window)
2196 {
2197         GError *error = NULL;
2198         
2199         ev_window_clear_progress_idle (ev_window);
2200         
2201         g_file_copy_finish (remote, async_result, &error);
2202         if (error) {
2203                 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
2204                         ev_window_error_message (ev_window, error,
2205                                                  "%s", _("Failed to reload document."));
2206                 g_error_free (error);
2207         } else {
2208                 ev_window_reload_local (ev_window);
2209         }
2210                 
2211         g_object_unref (remote);
2212 }
2213
2214 static void
2215 reload_remote_copy_progress_cb (goffset   n_bytes,
2216                                 goffset   total_bytes,
2217                                 EvWindow *ev_window)
2218 {
2219         gchar *status;
2220         gdouble fraction;
2221         
2222         if (!ev_window->priv->message_area)
2223                 return;
2224
2225         if (total_bytes <= 0)
2226                 return;
2227
2228         fraction = n_bytes / (gdouble)total_bytes;
2229         status = g_strdup_printf (_("Downloading document (%d%%)"),
2230                                   (gint)(fraction * 100));
2231         
2232         ev_progress_message_area_set_status (EV_PROGRESS_MESSAGE_AREA (ev_window->priv->message_area),
2233                                              status);
2234         ev_progress_message_area_set_fraction (EV_PROGRESS_MESSAGE_AREA (ev_window->priv->message_area),
2235                                                fraction);
2236
2237         g_free (status);
2238 }
2239
2240 static void
2241 query_remote_uri_mtime_cb (GFile        *remote,
2242                            GAsyncResult *async_result,
2243                            EvWindow     *ev_window)
2244 {
2245         GFileInfo *info;
2246         GTimeVal   mtime;
2247         GError    *error = NULL;
2248
2249         info = g_file_query_info_finish (remote, async_result, &error);
2250         if (error) {
2251                 g_error_free (error);
2252                 g_object_unref (remote);
2253                 ev_window_reload_local (ev_window);
2254
2255                 return;
2256         }
2257         
2258         g_file_info_get_modification_time (info, &mtime);
2259         if (ev_window->priv->uri_mtime != mtime.tv_sec) {
2260                 GFile *target_file;
2261                         
2262                 /* Remote file has changed */
2263                 ev_window->priv->uri_mtime = mtime.tv_sec;
2264
2265                 ev_window_reset_progress_cancellable (ev_window);
2266                 
2267                 target_file = g_file_new_for_uri (ev_window->priv->local_uri);
2268                 g_file_copy_async (remote, target_file,
2269                                    G_FILE_COPY_OVERWRITE,
2270                                    G_PRIORITY_DEFAULT,
2271                                    ev_window->priv->progress_cancellable,
2272                                    (GFileProgressCallback)reload_remote_copy_progress_cb,
2273                                    ev_window, 
2274                                    (GAsyncReadyCallback)reload_remote_copy_ready_cb,
2275                                    ev_window);
2276                 g_object_unref (target_file);
2277                 ev_window_show_progress_message (ev_window, 1,
2278                                                  (GSourceFunc)show_reloading_progress);
2279         } else {
2280                 g_object_unref (remote);
2281                 ev_window_reload_local (ev_window);
2282         }
2283         
2284         g_object_unref (info);
2285 }
2286
2287 static void
2288 ev_window_reload_remote (EvWindow *ev_window)
2289 {
2290         GFile *remote;
2291         
2292         remote = g_file_new_for_uri (ev_window->priv->uri);
2293         /* Reload the remote uri only if it has changed */
2294         g_file_query_info_async (remote,
2295                                  G_FILE_ATTRIBUTE_TIME_MODIFIED,
2296                                  0, G_PRIORITY_DEFAULT,
2297                                  NULL,
2298                                  (GAsyncReadyCallback)query_remote_uri_mtime_cb,
2299                                  ev_window);
2300 }
2301
2302 static void
2303 ev_window_reload_document (EvWindow *ev_window,
2304                            EvLinkDest *dest)
2305 {
2306         gint page;
2307
2308         
2309         ev_window_clear_reload_job (ev_window);
2310         ev_window->priv->in_reload = TRUE;
2311
2312         page = ev_document_model_get_page (ev_window->priv->model);
2313         
2314         if (ev_window->priv->dest)
2315                 g_object_unref (ev_window->priv->dest);
2316         ev_window->priv->dest = dest ? g_object_ref (dest) : NULL;
2317
2318         if (ev_window->priv->local_uri) {
2319                 ev_window_reload_remote (ev_window);
2320         } else {
2321                 ev_window_reload_local (ev_window);
2322         }
2323 }
2324
2325 static void
2326 file_open_dialog_response_cb (GtkWidget *chooser,
2327                               gint       response_id,
2328                               EvWindow  *ev_window)
2329 {
2330         if (response_id == GTK_RESPONSE_OK) {
2331                 GSList *uris;
2332                 gchar  *uri;
2333
2334                 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (chooser));
2335
2336                 ev_application_open_uri_list (EV_APP, uris,
2337                                               gtk_window_get_screen (GTK_WINDOW (ev_window)),
2338                                               gtk_get_current_event_time ());
2339
2340                 g_slist_foreach (uris, (GFunc)g_free, NULL);
2341                 g_slist_free (uris);
2342
2343                 uri = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (chooser));
2344                 ev_application_set_filechooser_uri (EV_APP,
2345                                                     GTK_FILE_CHOOSER_ACTION_OPEN,
2346                                                     uri);
2347                 g_free (uri);
2348         }
2349
2350         gtk_widget_destroy (chooser);
2351 }
2352
2353 static void
2354 ev_window_cmd_file_open (GtkAction *action, EvWindow *window)
2355 {
2356         GtkWidget   *chooser;
2357         const gchar *default_uri;
2358         gchar       *parent_uri = NULL;
2359
2360         chooser = gtk_file_chooser_dialog_new (_("Open Document"),
2361                                                GTK_WINDOW (window),
2362                                                GTK_FILE_CHOOSER_ACTION_OPEN,
2363                                                GTK_STOCK_CANCEL,
2364                                                GTK_RESPONSE_CANCEL,
2365                                                GTK_STOCK_OPEN, GTK_RESPONSE_OK,
2366                                                NULL);
2367
2368         ev_document_factory_add_filters (chooser, NULL);
2369         gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (chooser), TRUE);
2370         gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (chooser), FALSE);
2371
2372         default_uri = ev_application_get_filechooser_uri (EV_APP, GTK_FILE_CHOOSER_ACTION_OPEN);
2373         if (!default_uri && window->priv->uri) {
2374                 GFile *file, *parent;
2375
2376                 file = g_file_new_for_uri (window->priv->uri);
2377                 parent = g_file_get_parent (file);
2378                 if (parent) {
2379                         parent_uri = g_file_get_uri (parent);
2380                         default_uri = parent_uri;
2381                         g_object_unref (parent);
2382                 }
2383                 g_object_unref (file);
2384         }
2385
2386         if (default_uri) {
2387                 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (chooser), default_uri);
2388         } else {
2389                 const gchar *folder;
2390
2391                 folder = g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS);
2392                 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (chooser),
2393                                                      folder ? folder : g_get_home_dir ());
2394         }
2395         g_free (parent_uri);
2396
2397         g_signal_connect (chooser, "response",
2398                           G_CALLBACK (file_open_dialog_response_cb),
2399                           window);
2400
2401         gtk_widget_show (chooser);
2402 }
2403
2404 static void
2405 ev_window_open_copy_at_dest (EvWindow   *window,
2406                              EvLinkDest *dest)
2407 {
2408         EvWindow *new_window = EV_WINDOW (ev_window_new ());
2409
2410         ev_window_n_copies++;
2411
2412         if (window->priv->metadata)
2413                 new_window->priv->metadata = g_object_ref (window->priv->metadata);
2414         ev_window_open_document (new_window,
2415                                  window->priv->document,
2416                                  dest, 0, NULL);
2417         gtk_window_present (GTK_WINDOW (new_window));
2418 }
2419
2420 static void
2421 ev_window_cmd_file_open_copy (GtkAction *action, EvWindow *window)
2422 {
2423         ev_window_open_copy_at_dest (window, NULL);
2424 }
2425
2426 static void
2427 ev_window_cmd_recent_file_activate (GtkAction *action,
2428                                     EvWindow  *window)
2429 {
2430         GtkRecentInfo *info;
2431         const gchar   *uri;
2432
2433         info = g_object_get_data (G_OBJECT (action), "gtk-recent-info");
2434         g_assert (info != NULL);
2435         
2436         uri = gtk_recent_info_get_uri (info);
2437         
2438         ev_application_open_uri_at_dest (EV_APP, uri,
2439                                          gtk_window_get_screen (GTK_WINDOW (window)),
2440                                          NULL, 0, NULL, gtk_get_current_event_time ());
2441 }
2442
2443 static void
2444 ev_window_open_recent_action_item_activated (EvOpenRecentAction *action,
2445                                              const gchar        *uri,
2446                                              EvWindow           *window)
2447 {
2448         ev_application_open_uri_at_dest (EV_APP, uri,
2449                                          gtk_window_get_screen (GTK_WINDOW (window)),
2450                                          NULL, 0, NULL, gtk_get_current_event_time ());
2451 }
2452
2453 static void
2454 ev_window_add_recent (EvWindow *window, const char *filename)
2455 {
2456         gtk_recent_manager_add_item (window->priv->recent_manager, filename);
2457 }
2458
2459 static gint
2460 compare_recent_items (GtkRecentInfo *a, GtkRecentInfo *b)
2461 {
2462         gboolean     has_ev_a, has_ev_b;
2463         const gchar *evince = g_get_application_name ();
2464
2465         has_ev_a = gtk_recent_info_has_application (a, evince);
2466         has_ev_b = gtk_recent_info_has_application (b, evince);
2467         
2468         if (has_ev_a && has_ev_b) {
2469                 time_t time_a, time_b;
2470
2471                 time_a = gtk_recent_info_get_modified (a);
2472                 time_b = gtk_recent_info_get_modified (b);
2473
2474                 return (time_b - time_a);
2475         } else if (has_ev_a) {
2476                 return -1;
2477         } else if (has_ev_b) {
2478                 return 1;
2479         }
2480
2481         return 0;
2482 }
2483
2484 /*
2485  * Doubles underscore to avoid spurious menu accels.
2486  */
2487 static gchar * 
2488 ev_window_get_recent_file_label (gint index, const gchar *filename)
2489 {
2490         GString *str;
2491         gint length;
2492         const gchar *p;
2493         const gchar *end;
2494         gboolean is_rtl;
2495         
2496         is_rtl = (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL);
2497
2498         g_return_val_if_fail (filename != NULL, NULL);
2499         
2500         length = strlen (filename);
2501         str = g_string_sized_new (length + 10);
2502         g_string_printf (str, "%s_%d.  ", is_rtl ? "\xE2\x80\x8F" : "", index);
2503
2504         p = filename;
2505         end = filename + length;
2506  
2507         while (p != end) {
2508                 const gchar *next;
2509                 next = g_utf8_next_char (p);
2510  
2511                 switch (*p) {
2512                         case '_':
2513                                 g_string_append (str, "__");
2514                                 break;
2515                         default:
2516                                 g_string_append_len (str, p, next - p);
2517                                 break;
2518                 }
2519  
2520                 p = next;
2521         }
2522  
2523         return g_string_free (str, FALSE);
2524 }
2525
2526 static void
2527 ev_window_recent_action_connect_proxy_cb (GtkActionGroup *action_group,
2528                                           GtkAction *action,
2529                                           GtkWidget *proxy,
2530                                           gpointer data)
2531 {
2532         GtkLabel *label;
2533
2534         if (!GTK_IS_MENU_ITEM (proxy))
2535                 return;
2536
2537         label = GTK_LABEL (gtk_bin_get_child (GTK_BIN (proxy)));
2538
2539         gtk_label_set_ellipsize (label, PANGO_ELLIPSIZE_MIDDLE);
2540         gtk_label_set_max_width_chars (label, MAX_RECENT_ITEM_LEN);
2541 }
2542
2543 static void
2544 ev_window_setup_recent (EvWindow *ev_window)
2545 {
2546         GList        *items, *l;
2547         guint         n_items = 0;
2548         const gchar  *evince = g_get_application_name ();
2549         static guint  i = 0;
2550
2551         if (ev_window->priv->recent_ui_id > 0) {
2552                 gtk_ui_manager_remove_ui (ev_window->priv->ui_manager,
2553                                           ev_window->priv->recent_ui_id);
2554                 gtk_ui_manager_ensure_update (ev_window->priv->ui_manager);
2555         }
2556         ev_window->priv->recent_ui_id = gtk_ui_manager_new_merge_id (ev_window->priv->ui_manager);
2557
2558         if (ev_window->priv->recent_action_group) {
2559                 gtk_ui_manager_remove_action_group (ev_window->priv->ui_manager,
2560                                                     ev_window->priv->recent_action_group);
2561                 g_object_unref (ev_window->priv->recent_action_group);
2562         }
2563         ev_window->priv->recent_action_group = gtk_action_group_new ("RecentFilesActions");
2564         g_signal_connect (ev_window->priv->recent_action_group, "connect-proxy",
2565                           G_CALLBACK (ev_window_recent_action_connect_proxy_cb), NULL);
2566
2567         gtk_ui_manager_insert_action_group (ev_window->priv->ui_manager,
2568                                             ev_window->priv->recent_action_group, -1);
2569
2570         items = gtk_recent_manager_get_items (ev_window->priv->recent_manager);
2571         items = g_list_sort (items, (GCompareFunc) compare_recent_items);
2572
2573         for (l = items; l && l->data; l = g_list_next (l)) {
2574                 GtkRecentInfo *info;
2575                 GtkAction     *action;
2576                 gchar         *action_name;
2577                 gchar         *label;
2578                 const gchar   *mime_type;
2579                 gchar         *content_type;
2580                 GIcon         *icon = NULL;
2581
2582                 info = (GtkRecentInfo *) l->data;
2583
2584                 if (!gtk_recent_info_has_application (info, evince) ||
2585                     (gtk_recent_info_is_local (info) && !gtk_recent_info_exists (info)))
2586                         continue;
2587
2588                 action_name = g_strdup_printf ("RecentFile%u", i++);
2589                 label = ev_window_get_recent_file_label (
2590                         n_items + 1, gtk_recent_info_get_display_name (info));
2591
2592                 mime_type = gtk_recent_info_get_mime_type (info);
2593                 content_type = g_content_type_from_mime_type (mime_type);
2594                 if (content_type != NULL) {
2595                         icon = g_content_type_get_icon (content_type);
2596                         g_free (content_type);
2597                 }
2598
2599                 action = g_object_new (GTK_TYPE_ACTION,
2600                                        "name", action_name,
2601                                        "label", label,
2602                                        "gicon", icon,
2603                                        "always-show-image", TRUE,
2604                                        NULL);
2605
2606                 g_object_set_data_full (G_OBJECT (action),
2607                                         "gtk-recent-info",
2608                                         gtk_recent_info_ref (info),
2609                                         (GDestroyNotify) gtk_recent_info_unref);
2610                 
2611                 g_signal_connect (action, "activate",
2612                                   G_CALLBACK (ev_window_cmd_recent_file_activate),
2613                                   (gpointer) ev_window);
2614
2615                 gtk_action_group_add_action (ev_window->priv->recent_action_group,
2616                                              action);
2617                 g_object_unref (action);
2618
2619                 gtk_ui_manager_add_ui (ev_window->priv->ui_manager,
2620                                        ev_window->priv->recent_ui_id,
2621                                        "/MainMenu/FileMenu/RecentFilesMenu",
2622                                        label,
2623                                        action_name,
2624                                        GTK_UI_MANAGER_MENUITEM,
2625                                        FALSE);
2626                 g_free (action_name);
2627                 g_free (label);
2628                 if (icon != NULL)
2629                         g_object_unref (icon);
2630
2631                 if (++n_items == 5)
2632                         break;
2633         }
2634         
2635         g_list_foreach (items, (GFunc) gtk_recent_info_unref, NULL);
2636         g_list_free (items);
2637 }
2638
2639 static gboolean 
2640 show_saving_progress (GFile *dst)
2641 {
2642         EvWindow  *ev_window;
2643         GtkWidget *area;
2644         gchar     *text;
2645         gchar     *uri;
2646         EvSaveType save_type;
2647
2648         ev_window = EV_WINDOW (g_object_get_data (G_OBJECT (dst), "ev-window"));
2649         ev_window->priv->progress_idle = 0;
2650         
2651         if (ev_window->priv->message_area)
2652                 return FALSE;
2653
2654         save_type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dst), "save-type"));
2655         uri = g_file_get_uri (dst);
2656         switch (save_type) {
2657         case EV_SAVE_DOCUMENT:
2658                 text = g_strdup_printf (_("Saving document to %s"), uri);
2659                 break;
2660         case EV_SAVE_ATTACHMENT:
2661                 text = g_strdup_printf (_("Saving attachment to %s"), uri);
2662                 break;
2663         case EV_SAVE_IMAGE:
2664                 text = g_strdup_printf (_("Saving image to %s"), uri);
2665                 break;
2666         default:
2667                 g_assert_not_reached ();
2668         }
2669         g_free (uri);
2670         area = ev_progress_message_area_new (GTK_STOCK_SAVE,
2671                                              text,
2672                                              GTK_STOCK_CLOSE,
2673                                              GTK_RESPONSE_CLOSE,
2674                                              GTK_STOCK_CANCEL,
2675                                              GTK_RESPONSE_CANCEL,
2676                                              NULL);
2677         g_signal_connect (area, "response",
2678                           G_CALLBACK (ev_window_progress_response_cb),
2679                           ev_window);
2680         gtk_widget_show (area);
2681         ev_window_set_message_area (ev_window, area);
2682         g_free (text);
2683
2684         return FALSE;
2685 }
2686
2687 static void
2688 window_save_file_copy_ready_cb (GFile        *src,
2689                                 GAsyncResult *async_result,
2690                                 GFile        *dst)
2691 {
2692         EvWindow *ev_window;
2693         GError   *error = NULL;
2694
2695         ev_window = EV_WINDOW (g_object_get_data (G_OBJECT (dst), "ev-window"));
2696         ev_window_clear_progress_idle (ev_window);
2697         
2698         if (g_file_copy_finish (src, async_result, &error)) {
2699                 ev_tmp_file_unlink (src);
2700                 return;
2701         }
2702
2703         if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
2704                 gchar *name;
2705                 
2706                 name = g_file_get_basename (dst);
2707                 ev_window_error_message (ev_window, error,
2708                                          _("The file could not be saved as “%s”."),
2709                                          name);
2710                 g_free (name);
2711         }
2712         ev_tmp_file_unlink (src);
2713         g_error_free (error);
2714 }
2715
2716 static void
2717 window_save_file_copy_progress_cb (goffset n_bytes,
2718                                    goffset total_bytes,
2719                                    GFile  *dst)
2720 {
2721         EvWindow  *ev_window;
2722         EvSaveType save_type;
2723         gchar     *status;
2724         gdouble    fraction;
2725
2726         ev_window = EV_WINDOW (g_object_get_data (G_OBJECT (dst), "ev-window"));
2727         
2728         if (!ev_window->priv->message_area)
2729                 return;
2730
2731         if (total_bytes <= 0)
2732                 return;
2733
2734         fraction = n_bytes / (gdouble)total_bytes;
2735         save_type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dst), "save-type"));
2736
2737         switch (save_type) {
2738         case EV_SAVE_DOCUMENT:
2739                 status = g_strdup_printf (_("Uploading document (%d%%)"),
2740                                           (gint)(fraction * 100));
2741                 break;
2742         case EV_SAVE_ATTACHMENT:
2743                 status = g_strdup_printf (_("Uploading attachment (%d%%)"),
2744                                           (gint)(fraction * 100));
2745                 break;
2746         case EV_SAVE_IMAGE:
2747                 status = g_strdup_printf (_("Uploading image (%d%%)"),
2748                                           (gint)(fraction * 100));
2749                 break;
2750         default:
2751                 g_assert_not_reached ();
2752         }
2753         
2754         ev_progress_message_area_set_status (EV_PROGRESS_MESSAGE_AREA (ev_window->priv->message_area),
2755                                              status);
2756         ev_progress_message_area_set_fraction (EV_PROGRESS_MESSAGE_AREA (ev_window->priv->message_area),
2757                                                fraction);
2758
2759         g_free (status);
2760 }
2761
2762 static void
2763 ev_window_save_remote (EvWindow  *ev_window,
2764                        EvSaveType save_type,
2765                        GFile     *src,
2766                        GFile     *dst)
2767 {
2768         ev_window_reset_progress_cancellable (ev_window);
2769         g_object_set_data (G_OBJECT (dst), "ev-window", ev_window);
2770         g_object_set_data (G_OBJECT (dst), "save-type", GINT_TO_POINTER (save_type));
2771         g_file_copy_async (src, dst,
2772                            G_FILE_COPY_OVERWRITE,
2773                            G_PRIORITY_DEFAULT,
2774                            ev_window->priv->progress_cancellable,
2775                            (GFileProgressCallback)window_save_file_copy_progress_cb,
2776                            dst,
2777                            (GAsyncReadyCallback)window_save_file_copy_ready_cb,
2778                            dst);
2779         ev_window->priv->progress_idle =
2780                 g_timeout_add_seconds_full (G_PRIORITY_DEFAULT,
2781                                             1,
2782                                             (GSourceFunc)show_saving_progress,
2783                                             dst,
2784                                             NULL);
2785 }
2786
2787 static void
2788 ev_window_clear_save_job (EvWindow *ev_window)
2789 {
2790         if (ev_window->priv->save_job != NULL) {
2791                 if (!ev_job_is_finished (ev_window->priv->save_job))
2792                         ev_job_cancel (ev_window->priv->save_job);
2793                 
2794                 g_signal_handlers_disconnect_by_func (ev_window->priv->save_job,
2795                                                       ev_window_save_job_cb,
2796                                                       ev_window);
2797                 g_object_unref (ev_window->priv->save_job);
2798                 ev_window->priv->save_job = NULL;
2799         }
2800 }
2801
2802 static void
2803 ev_window_save_job_cb (EvJob     *job,
2804                        EvWindow  *window)
2805 {
2806         if (ev_job_is_failed (job)) {
2807                 ev_window_error_message (window, job->error,
2808                                          _("The file could not be saved as “%s”."),
2809                                          EV_JOB_SAVE (job)->uri);
2810         } else {
2811                 ev_window_add_recent (window, EV_JOB_SAVE (job)->uri);
2812         }
2813
2814         ev_window_clear_save_job (window);
2815 }
2816
2817 static void
2818 file_save_dialog_response_cb (GtkWidget *fc,
2819                               gint       response_id,
2820                               EvWindow  *ev_window)
2821 {
2822         gchar *uri;
2823         GFile *file, *parent;
2824
2825         if (response_id != GTK_RESPONSE_OK) {
2826                 gtk_widget_destroy (fc);
2827                 return;
2828         }
2829
2830         uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fc));
2831         file = g_file_new_for_uri (uri);
2832         parent = g_file_get_parent (file);
2833         g_object_unref (file);
2834         if (parent) {
2835                 gchar *folder_uri;
2836
2837                 folder_uri = g_file_get_uri (parent);
2838                 ev_application_set_filechooser_uri (EV_APP,
2839                                                     GTK_FILE_CHOOSER_ACTION_SAVE,
2840                                                     folder_uri);
2841                 g_free (folder_uri);
2842                 g_object_unref (parent);
2843         }
2844
2845         /* FIXME: remote copy should be done here rather than in the save job, 
2846          * so that we can track progress and cancel the operation
2847          */
2848
2849         ev_window_clear_save_job (ev_window);
2850         ev_window->priv->save_job = ev_job_save_new (ev_window->priv->document,
2851                                                      uri, ev_window->priv->uri);
2852         g_signal_connect (ev_window->priv->save_job, "finished",
2853                           G_CALLBACK (ev_window_save_job_cb),
2854                           ev_window);
2855         /* The priority doesn't matter for this job */
2856         ev_job_scheduler_push_job (ev_window->priv->save_job, EV_JOB_PRIORITY_NONE);
2857
2858         g_free (uri);
2859         gtk_widget_destroy (fc);
2860 }
2861
2862 static void
2863 ev_window_cmd_save_as (GtkAction *action, EvWindow *ev_window)
2864 {
2865         GtkWidget *fc;
2866         gchar *base_name;
2867         GFile *file;
2868         const gchar *default_uri;
2869
2870         fc = gtk_file_chooser_dialog_new (
2871                 _("Save a Copy"),
2872                 GTK_WINDOW (ev_window), GTK_FILE_CHOOSER_ACTION_SAVE,
2873                 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
2874                 GTK_STOCK_SAVE, GTK_RESPONSE_OK,
2875                 NULL);
2876
2877         ev_document_factory_add_filters (fc, ev_window->priv->document);
2878         gtk_dialog_set_default_response (GTK_DIALOG (fc), GTK_RESPONSE_OK);
2879         gtk_dialog_set_alternative_button_order (GTK_DIALOG (fc),
2880                                                 GTK_RESPONSE_OK,
2881                                                 GTK_RESPONSE_CANCEL,
2882                                                 -1);
2883
2884         gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (fc), FALSE);
2885         gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (fc), TRUE);
2886         file = g_file_new_for_uri (ev_window->priv->uri);
2887         base_name = g_file_get_basename (file);
2888         gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (fc), base_name);
2889
2890         default_uri = ev_application_get_filechooser_uri (EV_APP, GTK_FILE_CHOOSER_ACTION_SAVE);
2891         if (default_uri) {
2892                 gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (fc), default_uri);
2893         } else {
2894                 const gchar *folder;
2895
2896                 folder = g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS);
2897                 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (fc),
2898                                                      folder ? folder : g_get_home_dir ());
2899         }
2900
2901         g_object_unref (file);
2902         g_free (base_name);
2903
2904         g_signal_connect (fc, "response",
2905                           G_CALLBACK (file_save_dialog_response_cb),
2906                           ev_window);
2907
2908         gtk_widget_show (fc);
2909 }
2910
2911 static void
2912 ev_window_cmd_open_containing_folder (GtkAction *action, EvWindow *ev_window)
2913 {
2914         GtkWidget *ev_window_widget;
2915         GFile *file;
2916         GFile *parent;
2917
2918         ev_window_widget = GTK_WIDGET (ev_window);
2919
2920         file = g_file_new_for_uri (ev_window->priv->uri);
2921         parent = g_file_get_parent (file);
2922
2923         if (parent) {
2924                 char *parent_uri;
2925
2926                 parent_uri = g_file_get_uri (parent);
2927                 if (parent_uri) {
2928                         GdkScreen *screen;
2929                         guint32 timestamp;
2930                         GError *error;
2931
2932                         screen = gtk_widget_get_screen (ev_window_widget);
2933                         timestamp = gtk_get_current_event_time ();
2934
2935                         error = NULL;
2936                         if (!gtk_show_uri (screen, parent_uri, timestamp, &error)) {
2937                                 ev_window_error_message (ev_window, error, _("Could not open the containing folder"));
2938                                 g_error_free (error);
2939                         }
2940
2941                         g_free (parent_uri);
2942                 }
2943         }
2944
2945         if (file)
2946                 g_object_unref (file);
2947
2948         if (parent)
2949                 g_object_unref (parent);
2950         
2951 }
2952
2953 static GKeyFile *
2954 get_print_settings_file (void)
2955 {
2956         GKeyFile *print_settings_file;
2957         gchar    *filename;
2958         GError *error = NULL;
2959
2960         print_settings_file = g_key_file_new ();
2961
2962         filename = g_build_filename (ev_application_get_dot_dir (EV_APP, FALSE),
2963                                      EV_PRINT_SETTINGS_FILE, NULL);
2964         if (!g_key_file_load_from_file (print_settings_file,
2965                                         filename,
2966                                         G_KEY_FILE_KEEP_COMMENTS |
2967                                         G_KEY_FILE_KEEP_TRANSLATIONS,
2968                                         &error)) {
2969
2970                 /* Don't warn if the file simply doesn't exist */
2971                 if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
2972                         g_warning ("%s", error->message);
2973
2974                 g_error_free (error);
2975         }
2976
2977         g_free (filename);
2978
2979         return print_settings_file;
2980 }
2981
2982 static void
2983 save_print_setting_file (GKeyFile *key_file)
2984 {
2985         gchar  *filename;
2986         gchar  *data;
2987         gsize  data_length;
2988         GError *error = NULL;
2989
2990         filename = g_build_filename (ev_application_get_dot_dir (EV_APP, TRUE),
2991                                      EV_PRINT_SETTINGS_FILE, NULL);
2992         data = g_key_file_to_data (key_file, &data_length, NULL);
2993         g_file_set_contents (filename, data, data_length, &error);
2994         if (error) {
2995                 g_warning ("Failed to save print settings: %s", error->message);
2996                 g_error_free (error);
2997         }
2998         g_free (data);
2999         g_free (filename);
3000 }
3001
3002 static void
3003 ev_window_save_print_settings (EvWindow         *window,
3004                                GtkPrintSettings *print_settings)
3005 {
3006         GKeyFile *key_file;
3007         gint      i;
3008
3009         key_file = get_print_settings_file ();
3010         gtk_print_settings_to_key_file (print_settings, key_file, EV_PRINT_SETTINGS_GROUP);
3011
3012         /* Save print settings that are specific to the document */
3013         for (i = 0; i < G_N_ELEMENTS (document_print_settings); i++) {
3014                 /* Remove it from global settings */
3015                 g_key_file_remove_key (key_file, EV_PRINT_SETTINGS_GROUP,
3016                                        document_print_settings[i], NULL);
3017
3018                 if (window->priv->metadata) {
3019                         const gchar *value;
3020
3021                         value = gtk_print_settings_get (print_settings,
3022                                                         document_print_settings[i]);
3023                         ev_metadata_set_string (window->priv->metadata,
3024                                                 document_print_settings[i], value);
3025                 }
3026         }
3027
3028         save_print_setting_file (key_file);
3029         g_key_file_free (key_file);
3030 }
3031
3032 static void
3033 ev_window_save_print_page_setup (EvWindow     *window,
3034                                  GtkPageSetup *page_setup)
3035 {
3036         GKeyFile *key_file;
3037
3038         key_file = get_print_settings_file ();
3039         gtk_page_setup_to_key_file (page_setup, key_file, EV_PAGE_SETUP_GROUP);
3040
3041         /* Do not save document settings in global file */
3042         g_key_file_remove_key (key_file, EV_PAGE_SETUP_GROUP,
3043                                "page-setup-orientation", NULL);
3044         g_key_file_remove_key (key_file, EV_PAGE_SETUP_GROUP,
3045                                "page-setup-margin-top", NULL);
3046         g_key_file_remove_key (key_file, EV_PAGE_SETUP_GROUP,
3047                                "page-setup-margin-bottom", NULL);
3048         g_key_file_remove_key (key_file, EV_PAGE_SETUP_GROUP,
3049                                "page-setup-margin-left", NULL);
3050         g_key_file_remove_key (key_file, EV_PAGE_SETUP_GROUP,
3051                                "page-setup-margin-right", NULL);
3052
3053         save_print_setting_file (key_file);
3054         g_key_file_free (key_file);
3055
3056         if (!window->priv->metadata)
3057                 return;
3058
3059         /* Save page setup options that are specific to the document */
3060         ev_metadata_set_int (window->priv->metadata, "page-setup-orientation",
3061                              gtk_page_setup_get_orientation (page_setup));
3062         ev_metadata_set_double (window->priv->metadata, "page-setup-margin-top",
3063                                 gtk_page_setup_get_top_margin (page_setup, GTK_UNIT_MM));
3064         ev_metadata_set_double (window->priv->metadata, "page-setup-margin-bottom",
3065                                 gtk_page_setup_get_bottom_margin (page_setup, GTK_UNIT_MM));
3066         ev_metadata_set_double (window->priv->metadata, "page-setup-margin-left",
3067                                 gtk_page_setup_get_left_margin (page_setup, GTK_UNIT_MM));
3068         ev_metadata_set_double (window->priv->metadata, "page-setup-margin-right",
3069                                 gtk_page_setup_get_right_margin (page_setup, GTK_UNIT_MM));
3070 }
3071
3072 static void
3073 ev_window_load_print_settings_from_metadata (EvWindow         *window,
3074                                              GtkPrintSettings *print_settings)
3075 {
3076         gint i;
3077
3078         if (!window->priv->metadata)
3079                 return;
3080
3081         /* Load print setting that are specific to the document */
3082         for (i = 0; i < G_N_ELEMENTS (document_print_settings); i++) {
3083                 gchar *value = NULL;
3084
3085                 ev_metadata_get_string (window->priv->metadata,
3086                                         document_print_settings[i], &value);
3087                 gtk_print_settings_set (print_settings,
3088                                         document_print_settings[i], value);
3089         }
3090 }
3091
3092 static void
3093 ev_window_load_print_page_setup_from_metadata (EvWindow     *window,
3094                                                GtkPageSetup *page_setup)
3095 {
3096         gint          int_value;
3097         gdouble       double_value;
3098         GtkPaperSize *paper_size = gtk_page_setup_get_paper_size (page_setup);
3099
3100         /* Load page setup options that are specific to the document */
3101         if (window->priv->metadata &&
3102             ev_metadata_get_int (window->priv->metadata, "page-setup-orientation", &int_value)) {
3103                 gtk_page_setup_set_orientation (page_setup, int_value);
3104         } else {
3105                 gtk_page_setup_set_orientation (page_setup, GTK_PAGE_ORIENTATION_PORTRAIT);
3106         }
3107
3108         if (window->priv->metadata &&
3109             ev_metadata_get_double (window->priv->metadata, "page-setup-margin-top", &double_value)) {
3110                 gtk_page_setup_set_top_margin (page_setup, double_value, GTK_UNIT_MM);
3111         } else {
3112                 gtk_page_setup_set_top_margin (page_setup,
3113                                                gtk_paper_size_get_default_top_margin (paper_size, GTK_UNIT_MM),
3114                                                GTK_UNIT_MM);
3115         }
3116
3117         if (window->priv->metadata &&
3118             ev_metadata_get_double (window->priv->metadata, "page-setup-margin-bottom", &double_value)) {
3119                 gtk_page_setup_set_bottom_margin (page_setup, double_value, GTK_UNIT_MM);
3120         } else {
3121                 gtk_page_setup_set_bottom_margin (page_setup,
3122                                                   gtk_paper_size_get_default_bottom_margin (paper_size, GTK_UNIT_MM),
3123                                                   GTK_UNIT_MM);
3124         }
3125
3126         if (window->priv->metadata &&
3127             ev_metadata_get_double (window->priv->metadata, "page-setup-margin-left", &double_value)) {
3128                 gtk_page_setup_set_left_margin (page_setup, double_value, GTK_UNIT_MM);
3129         } else {
3130                 gtk_page_setup_set_left_margin (page_setup,
3131                                                 gtk_paper_size_get_default_left_margin (paper_size, GTK_UNIT_MM),
3132                                                 GTK_UNIT_MM);
3133         }
3134
3135         if (window->priv->metadata &&
3136             ev_metadata_get_double (window->priv->metadata, "page-setup-margin-right", &double_value)) {
3137                 gtk_page_setup_set_right_margin (page_setup, double_value, GTK_UNIT_MM);
3138         } else {
3139                 gtk_page_setup_set_right_margin (page_setup,
3140                                                  gtk_paper_size_get_default_right_margin (paper_size, GTK_UNIT_MM),
3141                                                  GTK_UNIT_MM);
3142         }
3143 }
3144
3145 static GtkPrintSettings *
3146 get_print_settings (GKeyFile *key_file)
3147 {
3148         GtkPrintSettings *print_settings;
3149
3150         print_settings = g_key_file_has_group (key_file, EV_PRINT_SETTINGS_GROUP) ?
3151                 gtk_print_settings_new_from_key_file (key_file, EV_PRINT_SETTINGS_GROUP, NULL) :
3152                 gtk_print_settings_new ();
3153
3154         return print_settings ? print_settings : gtk_print_settings_new ();
3155 }
3156
3157 static GtkPageSetup *
3158 get_print_page_setup (GKeyFile *key_file)
3159 {
3160         GtkPageSetup *page_setup;
3161
3162         page_setup = g_key_file_has_group (key_file, EV_PAGE_SETUP_GROUP) ?
3163                 gtk_page_setup_new_from_key_file (key_file, EV_PAGE_SETUP_GROUP, NULL) :
3164                 gtk_page_setup_new ();
3165
3166         return page_setup ? page_setup : gtk_page_setup_new ();
3167 }
3168
3169 static void
3170 ev_window_print_cancel (EvWindow *ev_window)
3171 {
3172         EvPrintOperation *op;
3173         
3174         if (!ev_window->priv->print_queue)
3175                 return;
3176
3177         while ((op = g_queue_peek_tail (ev_window->priv->print_queue))) {
3178                 ev_print_operation_cancel (op);
3179         }
3180 }
3181
3182 static void
3183 ev_window_print_update_pending_jobs_message (EvWindow *ev_window,
3184                                              gint      n_jobs)
3185 {
3186         gchar *text = NULL;
3187         
3188         if (!EV_IS_PROGRESS_MESSAGE_AREA (ev_window->priv->message_area) ||
3189             !ev_window->priv->print_queue)
3190                 return;
3191
3192         if (n_jobs == 0) {
3193                 ev_window_set_message_area (ev_window, NULL);
3194                 return;
3195         }
3196         
3197         if (n_jobs > 1) {
3198                 text = g_strdup_printf (ngettext ("%d pending job in queue",
3199                                                   "%d pending jobs in queue",
3200                                                   n_jobs - 1), n_jobs - 1);
3201         }
3202
3203         ev_message_area_set_secondary_text (EV_MESSAGE_AREA (ev_window->priv->message_area),
3204                                             text);
3205         g_free (text);
3206 }
3207
3208 static gboolean
3209 destroy_window (GtkWidget *window)
3210 {
3211         gtk_widget_destroy (window);
3212         
3213         return FALSE;
3214 }
3215
3216 static void
3217 ev_window_print_operation_done (EvPrintOperation       *op,
3218                                 GtkPrintOperationResult result,
3219                                 EvWindow               *ev_window)
3220 {
3221         gint n_jobs;
3222
3223         switch (result) {
3224         case GTK_PRINT_OPERATION_RESULT_APPLY: {
3225                 GtkPrintSettings *print_settings;
3226
3227                 print_settings = ev_print_operation_get_print_settings (op);
3228                 ev_window_save_print_settings (ev_window, print_settings);
3229
3230                 if (ev_print_operation_get_embed_page_setup (op)) {
3231                         GtkPageSetup *page_setup;
3232
3233                         page_setup = ev_print_operation_get_default_page_setup (op);
3234                         ev_window_save_print_page_setup (ev_window, page_setup);
3235                 }
3236         }
3237
3238                 break;
3239         case GTK_PRINT_OPERATION_RESULT_ERROR: {
3240                 GtkWidget *dialog;
3241                 GError    *error = NULL;
3242
3243
3244                 ev_print_operation_get_error (op, &error);
3245                 
3246                 /* The message area is already used by
3247                  * the printing progress, so it's better to
3248                  * use a popup dialog in this case
3249                  */
3250                 dialog = gtk_message_dialog_new (GTK_WINDOW (ev_window),
3251                                                  GTK_DIALOG_DESTROY_WITH_PARENT,
3252                                                  GTK_MESSAGE_ERROR,
3253                                                  GTK_BUTTONS_CLOSE,
3254                                                  "%s", _("Failed to print document"));
3255                 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
3256                                                           "%s", error->message);
3257                 g_signal_connect (dialog, "response",
3258                                   G_CALLBACK (gtk_widget_destroy),
3259                                   NULL);
3260                 gtk_widget_show (dialog);
3261                 
3262                 g_error_free (error);
3263         }
3264                 break;
3265         case GTK_PRINT_OPERATION_RESULT_CANCEL:
3266         default:
3267                 break;
3268         }
3269
3270         g_queue_remove (ev_window->priv->print_queue, op);
3271         g_object_unref (op);
3272         n_jobs = g_queue_get_length (ev_window->priv->print_queue);
3273         ev_window_print_update_pending_jobs_message (ev_window, n_jobs);
3274
3275         if (n_jobs == 0 && ev_window->priv->close_after_print)
3276                 g_idle_add ((GSourceFunc)destroy_window,
3277                             ev_window);
3278 }
3279
3280 static void
3281 ev_window_print_progress_response_cb (EvProgressMessageArea *area,
3282                                       gint                   response,
3283                                       EvWindow              *ev_window)
3284 {
3285         if (response == GTK_RESPONSE_CANCEL) {
3286                 EvPrintOperation *op;
3287
3288                 op = g_queue_peek_tail (ev_window->priv->print_queue);
3289                 ev_print_operation_cancel (op);
3290         } else {
3291                 gtk_widget_hide (GTK_WIDGET (area));
3292         }
3293 }
3294
3295 static void
3296 ev_window_print_operation_status_changed (EvPrintOperation *op,
3297                                           EvWindow         *ev_window)
3298 {
3299         const gchar *status;
3300         gdouble      fraction;
3301
3302         status = ev_print_operation_get_status (op);
3303         fraction = ev_print_operation_get_progress (op);
3304         
3305         if (!ev_window->priv->message_area) {
3306                 GtkWidget   *area;
3307                 const gchar *job_name;
3308                 gchar       *text;
3309
3310                 job_name = ev_print_operation_get_job_name (op);
3311                 text = g_strdup_printf (_("Printing job “%s”"), job_name);
3312
3313                 area = ev_progress_message_area_new (GTK_STOCK_PRINT,
3314                                                      text,
3315                                                      GTK_STOCK_CLOSE,
3316                                                      GTK_RESPONSE_CLOSE,
3317                                                      GTK_STOCK_CANCEL,
3318                                                      GTK_RESPONSE_CANCEL,
3319                                                      NULL);
3320                 ev_window_print_update_pending_jobs_message (ev_window, 1);
3321                 g_signal_connect (area, "response",
3322                                   G_CALLBACK (ev_window_print_progress_response_cb),
3323                                   ev_window);
3324                 gtk_widget_show (area);
3325                 ev_window_set_message_area (ev_window, area);
3326                 g_free (text);
3327         }
3328
3329         ev_progress_message_area_set_status (EV_PROGRESS_MESSAGE_AREA (ev_window->priv->message_area),
3330                                              status);
3331         ev_progress_message_area_set_fraction (EV_PROGRESS_MESSAGE_AREA (ev_window->priv->message_area),
3332                                                fraction);
3333 }
3334
3335 static void
3336 ev_window_print_operation_begin_print (EvPrintOperation *op,
3337                                        EvWindow         *ev_window)
3338 {
3339         if (!ev_window->priv->print_queue)
3340                 ev_window->priv->print_queue = g_queue_new ();
3341
3342         g_queue_push_head (ev_window->priv->print_queue, op);
3343         ev_window_print_update_pending_jobs_message (ev_window,
3344                                                      g_queue_get_length (ev_window->priv->print_queue));
3345 }
3346
3347 void
3348 ev_window_print_range (EvWindow *ev_window,
3349                        gint      first_page,
3350                        gint      last_page)
3351 {
3352         EvPrintOperation *op;
3353         GKeyFile         *print_settings_file;
3354         GtkPrintSettings *print_settings;
3355         GtkPageSetup     *print_page_setup;
3356         gint              current_page;
3357         gint              document_last_page;
3358         gboolean          embed_page_setup;
3359
3360         g_return_if_fail (EV_IS_WINDOW (ev_window));
3361         g_return_if_fail (ev_window->priv->document != NULL);
3362
3363         if (!ev_window->priv->print_queue)
3364                 ev_window->priv->print_queue = g_queue_new ();
3365
3366         op = ev_print_operation_new (ev_window->priv->document);
3367         if (!op) {
3368                 g_warning ("%s", "Printing is not supported for document\n");
3369                 return;
3370         }
3371
3372         g_signal_connect (op, "begin_print",
3373                           G_CALLBACK (ev_window_print_operation_begin_print),
3374                           (gpointer)ev_window);
3375         g_signal_connect (op, "status_changed",
3376                           G_CALLBACK (ev_window_print_operation_status_changed),
3377                           (gpointer)ev_window);
3378         g_signal_connect (op, "done",
3379                           G_CALLBACK (ev_window_print_operation_done),
3380                           (gpointer)ev_window);
3381
3382         current_page = ev_document_model_get_page (ev_window->priv->model);
3383         document_last_page = ev_document_get_n_pages (ev_window->priv->document);
3384
3385         print_settings_file = get_print_settings_file ();
3386
3387         print_settings = get_print_settings (print_settings_file);
3388         ev_window_load_print_settings_from_metadata (ev_window, print_settings);
3389
3390         print_page_setup = get_print_page_setup (print_settings_file);
3391         ev_window_load_print_page_setup_from_metadata (ev_window, print_page_setup);
3392
3393         if (first_page != 1 || last_page != document_last_page) {
3394                 GtkPageRange range;
3395
3396                 /* Ranges in GtkPrint are 0 - N */
3397                 range.start = first_page - 1;
3398                 range.end = last_page - 1;
3399
3400                 gtk_print_settings_set_print_pages (print_settings,
3401                                                     GTK_PRINT_PAGES_RANGES);
3402                 gtk_print_settings_set_page_ranges (print_settings,
3403                                                     &range, 1);
3404         }
3405
3406         ev_print_operation_set_job_name (op, gtk_window_get_title (GTK_WINDOW (ev_window)));
3407         ev_print_operation_set_current_page (op, current_page);
3408         ev_print_operation_set_print_settings (op, print_settings);
3409         ev_print_operation_set_default_page_setup (op, print_page_setup);
3410         embed_page_setup = ev_window->priv->lockdown_settings ?
3411                 !g_settings_get_boolean (ev_window->priv->lockdown_settings,
3412                                          GS_LOCKDOWN_PRINT_SETUP) :
3413                 TRUE;
3414         ev_print_operation_set_embed_page_setup (op, embed_page_setup);
3415
3416         g_object_unref (print_settings);
3417         g_object_unref (print_page_setup);
3418         g_key_file_free (print_settings_file);
3419
3420         ev_print_operation_run (op, GTK_WINDOW (ev_window));
3421 }
3422
3423 static void
3424 ev_window_print (EvWindow *window)
3425 {
3426         ev_window_print_range (window, 1,
3427                                ev_document_get_n_pages (window->priv->document));
3428 }
3429
3430 static void
3431 ev_window_cmd_file_print (GtkAction *action, EvWindow *ev_window)
3432 {
3433         ev_window_print (ev_window);
3434 }
3435
3436 static void
3437 ev_window_cmd_file_properties (GtkAction *action, EvWindow *ev_window)
3438 {
3439         if (ev_window->priv->properties == NULL) {
3440                 ev_window->priv->properties = ev_properties_dialog_new ();
3441                 ev_properties_dialog_set_document (EV_PROPERTIES_DIALOG (ev_window->priv->properties),
3442                                                    ev_window->priv->uri,
3443                                                    ev_window->priv->document);
3444                 g_object_add_weak_pointer (G_OBJECT (ev_window->priv->properties),
3445                                            (gpointer) &(ev_window->priv->properties));
3446                 gtk_window_set_transient_for (GTK_WINDOW (ev_window->priv->properties),
3447                                               GTK_WINDOW (ev_window));
3448         }
3449
3450         ev_document_fc_mutex_lock ();
3451         gtk_widget_show (ev_window->priv->properties);
3452         ev_document_fc_mutex_unlock ();
3453 }
3454
3455 static void
3456 document_modified_confirmation_dialog_response (GtkDialog *dialog,
3457                                                 gint       response,
3458                                                 EvWindow  *ev_window)
3459 {
3460         gtk_widget_destroy (GTK_WIDGET (dialog));
3461
3462         switch (response) {
3463         case GTK_RESPONSE_YES:
3464                 ev_window_cmd_save_as (NULL, ev_window);
3465                 break;
3466         case GTK_RESPONSE_NO:
3467                 gtk_widget_destroy (GTK_WIDGET (ev_window));
3468                 break;
3469         case GTK_RESPONSE_CANCEL:
3470         default:
3471                 break;
3472         }
3473 }
3474
3475 static gboolean
3476 ev_window_check_document_modified (EvWindow *ev_window)
3477 {
3478         EvDocument  *document = ev_window->priv->document;
3479         GtkWidget   *dialog;
3480         gchar       *text, *markup;
3481         const gchar *secondary_text;
3482
3483         if (!document)
3484                 return FALSE;
3485
3486         if (EV_IS_DOCUMENT_FORMS (document) &&
3487             ev_document_forms_document_is_modified (EV_DOCUMENT_FORMS (document))) {
3488                 secondary_text = _("Document contains form fields that have been filled out. "
3489                                    "If you don't save a copy, changes will be permanently lost.");
3490         } else if (EV_IS_DOCUMENT_ANNOTATIONS (document) &&
3491                    ev_document_annotations_document_is_modified (EV_DOCUMENT_ANNOTATIONS (document))) {
3492                 secondary_text = _("Document contains new or modified annotations. "
3493                                    "If you don't save a copy, changes will be permanently lost.");
3494         } else {
3495                 return FALSE;
3496         }
3497
3498
3499         text = g_markup_printf_escaped (_("Save a copy of document “%s” before closing?"),
3500                                         gtk_window_get_title (GTK_WINDOW (ev_window)));
3501
3502         dialog = gtk_message_dialog_new (GTK_WINDOW (ev_window),
3503                                          GTK_DIALOG_MODAL,
3504                                          GTK_MESSAGE_QUESTION,
3505                                          GTK_BUTTONS_NONE,
3506                                          NULL);
3507
3508         markup = g_strdup_printf ("<b>%s</b>", text);
3509         g_free (text);
3510
3511         gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), markup);
3512         g_free (markup);
3513
3514         gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
3515                                                   "%s", secondary_text);
3516
3517         gtk_dialog_add_buttons (GTK_DIALOG (dialog),
3518                                 _("Close _without Saving"),
3519                                 GTK_RESPONSE_NO,
3520                                 GTK_STOCK_CANCEL,
3521                                 GTK_RESPONSE_CANCEL,
3522                                 _("Save a _Copy"),
3523                                 GTK_RESPONSE_YES,
3524                                 NULL);
3525         gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES);
3526         gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
3527                                                  GTK_RESPONSE_YES,
3528                                                  GTK_RESPONSE_NO,
3529                                                  GTK_RESPONSE_CANCEL,
3530                                                  -1);
3531
3532         g_signal_connect (dialog, "response",
3533                           G_CALLBACK (document_modified_confirmation_dialog_response),
3534                           ev_window);
3535         gtk_widget_show (dialog);
3536
3537         return TRUE;
3538 }
3539
3540 static void
3541 print_jobs_confirmation_dialog_response (GtkDialog *dialog,
3542                                          gint       response,
3543                                          EvWindow  *ev_window)
3544 {
3545         gtk_widget_destroy (GTK_WIDGET (dialog));       
3546         
3547         switch (response) {
3548         case GTK_RESPONSE_YES:
3549                 if (!ev_window->priv->print_queue ||
3550                     g_queue_is_empty (ev_window->priv->print_queue))
3551                         gtk_widget_destroy (GTK_WIDGET (ev_window));
3552                 else
3553                         ev_window->priv->close_after_print = TRUE;
3554                 break;
3555         case GTK_RESPONSE_NO:
3556                 ev_window->priv->close_after_print = TRUE;
3557                 if (ev_window->priv->print_queue &&
3558                     !g_queue_is_empty (ev_window->priv->print_queue)) {
3559                         gtk_widget_set_sensitive (GTK_WIDGET (ev_window), FALSE);
3560                         ev_window_print_cancel (ev_window);
3561                 } else {
3562                         gtk_widget_destroy (GTK_WIDGET (ev_window));
3563                 }
3564                 break;
3565         case GTK_RESPONSE_CANCEL:
3566         default:
3567                 ev_window->priv->close_after_print = FALSE;
3568         }
3569 }
3570
3571 static gboolean
3572 ev_window_check_print_queue (EvWindow *ev_window)
3573 {
3574         GtkWidget *dialog;
3575         gchar     *text, *markup;
3576         gint       n_print_jobs;
3577
3578         n_print_jobs = ev_window->priv->print_queue ?
3579                 g_queue_get_length (ev_window->priv->print_queue) : 0;
3580
3581         if (n_print_jobs == 0)
3582                 return FALSE;
3583
3584         dialog = gtk_message_dialog_new (GTK_WINDOW (ev_window),
3585                                          GTK_DIALOG_MODAL,
3586                                          GTK_MESSAGE_QUESTION,
3587                                          GTK_BUTTONS_NONE,
3588                                          NULL);
3589         if (n_print_jobs == 1) {
3590                 EvPrintOperation *op;
3591                 const gchar      *job_name;
3592
3593                 op = g_queue_peek_tail (ev_window->priv->print_queue);
3594                 job_name = ev_print_operation_get_job_name (op);
3595
3596                 text = g_strdup_printf (_("Wait until print job “%s” finishes before closing?"),
3597                                         job_name);
3598         } else {
3599                 text = g_strdup_printf (_("There are %d print jobs active. "
3600                                           "Wait until print finishes before closing?"),
3601                                         n_print_jobs);
3602         }
3603
3604         markup = g_strdup_printf ("<b>%s</b>", text);
3605         g_free (text);
3606
3607         gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), markup);
3608         g_free (markup);
3609
3610         gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s",
3611                                                   _("If you close the window, pending print "
3612                                                     "jobs will not be printed."));
3613
3614         gtk_dialog_add_buttons (GTK_DIALOG (dialog),
3615                                 _("Cancel _print and Close"),
3616                                 GTK_RESPONSE_NO,
3617                                 GTK_STOCK_CANCEL,
3618                                 GTK_RESPONSE_CANCEL,
3619                                 _("Close _after Printing"),
3620                                 GTK_RESPONSE_YES,
3621                                 NULL);
3622         gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES);
3623         gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
3624                                                  GTK_RESPONSE_YES,
3625                                                  GTK_RESPONSE_NO,
3626                                                  GTK_RESPONSE_CANCEL,
3627                                                  -1);
3628
3629         g_signal_connect (dialog, "response",
3630                           G_CALLBACK (print_jobs_confirmation_dialog_response),
3631                           ev_window);
3632         gtk_widget_show (dialog);
3633
3634         return TRUE;
3635 }
3636
3637 static gboolean
3638 ev_window_close (EvWindow *ev_window)
3639 {
3640         if (EV_WINDOW_IS_PRESENTATION (ev_window)) {
3641                 gint current_page;
3642
3643                 /* Save current page */
3644                 current_page = ev_view_presentation_get_current_page (
3645                         EV_VIEW_PRESENTATION (ev_window->priv->presentation_view));
3646                 ev_document_model_set_page (ev_window->priv->model, current_page);
3647         }
3648
3649         if (ev_window_check_document_modified (ev_window))
3650                 return FALSE;
3651
3652         if (ev_window_check_print_queue (ev_window))
3653                 return FALSE;
3654
3655         return TRUE;
3656 }
3657
3658 static void
3659 ev_window_cmd_file_close_window (GtkAction *action, EvWindow *ev_window)
3660 {
3661         if (ev_window_close (ev_window))
3662                 gtk_widget_destroy (GTK_WIDGET (ev_window));
3663 }
3664
3665 static void
3666 ev_window_cmd_focus_page_selector (GtkAction *act, EvWindow *window)
3667 {
3668         GtkAction *action;
3669         
3670         update_chrome_flag (window, EV_CHROME_RAISE_TOOLBAR, TRUE);
3671         ev_window_set_action_sensitive (window, "ViewToolbar", FALSE);
3672         update_chrome_visibility (window);
3673         
3674         action = gtk_action_group_get_action (window->priv->action_group,
3675                                               PAGE_SELECTOR_ACTION);
3676         ev_page_action_grab_focus (EV_PAGE_ACTION (action));
3677 }
3678
3679 static void
3680 ev_window_cmd_scroll_forward (GtkAction *action, EvWindow *window)
3681 {
3682         ev_view_scroll (EV_VIEW (window->priv->view), GTK_SCROLL_PAGE_FORWARD, FALSE);
3683 }
3684
3685 static void
3686 ev_window_cmd_scroll_backward (GtkAction *action, EvWindow *window)
3687 {
3688         ev_view_scroll (EV_VIEW (window->priv->view), GTK_SCROLL_PAGE_BACKWARD, FALSE);
3689 }
3690
3691 static void
3692 ev_window_cmd_continuous (GtkAction *action, EvWindow *ev_window)
3693 {
3694         gboolean continuous;
3695
3696         ev_window_stop_presentation (ev_window, TRUE);
3697         continuous = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
3698         ev_document_model_set_continuous (ev_window->priv->model, continuous);
3699 }
3700
3701 static void
3702 ev_window_cmd_dual (GtkAction *action, EvWindow *ev_window)
3703 {
3704         gboolean dual_page;
3705
3706         ev_window_stop_presentation (ev_window, TRUE);
3707         dual_page = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
3708         ev_document_model_set_dual_page (ev_window->priv->model, dual_page);
3709 }
3710
3711 static void
3712 ev_window_cmd_view_best_fit (GtkAction *action, EvWindow *ev_window)
3713 {
3714         ev_window_stop_presentation (ev_window, TRUE);
3715
3716         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
3717                 ev_document_model_set_sizing_mode (ev_window->priv->model, EV_SIZING_BEST_FIT);
3718         } else {
3719                 ev_document_model_set_sizing_mode (ev_window->priv->model, EV_SIZING_FREE);
3720         }
3721         ev_window_update_actions (ev_window);
3722 }
3723
3724 static void
3725 ev_window_cmd_view_page_width (GtkAction *action, EvWindow *ev_window)
3726 {
3727         ev_window_stop_presentation (ev_window, TRUE);
3728
3729         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) {
3730                 ev_document_model_set_sizing_mode (ev_window->priv->model, EV_SIZING_FIT_WIDTH);
3731         } else {
3732                 ev_document_model_set_sizing_mode (ev_window->priv->model, EV_SIZING_FREE);
3733         }
3734         ev_window_update_actions (ev_window);
3735 }
3736
3737
3738 static void
3739 ev_window_cmd_edit_select_all (GtkAction *action, EvWindow *ev_window)
3740 {
3741         g_return_if_fail (EV_IS_WINDOW (ev_window));
3742
3743         ev_view_select_all (EV_VIEW (ev_window->priv->view));
3744 }
3745
3746 static void
3747 ev_window_cmd_edit_find (GtkAction *action, EvWindow *ev_window)
3748 {
3749         g_return_if_fail (EV_IS_WINDOW (ev_window));
3750
3751         if (ev_window->priv->document == NULL || !EV_IS_DOCUMENT_FIND (ev_window->priv->document)) {
3752                 g_error ("Find action should be insensitive since document doesn't support find");
3753                 return;
3754         } 
3755
3756         update_chrome_flag (ev_window, EV_CHROME_FINDBAR, TRUE);
3757         update_chrome_visibility (ev_window);
3758         gtk_widget_grab_focus (ev_window->priv->find_bar);
3759 }
3760
3761 static void
3762 ev_window_cmd_edit_find_next (GtkAction *action, EvWindow *ev_window)
3763 {
3764         g_return_if_fail (EV_IS_WINDOW (ev_window));
3765
3766         update_chrome_flag (ev_window, EV_CHROME_FINDBAR, TRUE);
3767         update_chrome_visibility (ev_window);
3768         gtk_widget_grab_focus (ev_window->priv->find_bar);
3769         ev_view_find_next (EV_VIEW (ev_window->priv->view));
3770 }
3771
3772 static void
3773 ev_window_cmd_edit_find_previous (GtkAction *action, EvWindow *ev_window)
3774 {
3775         g_return_if_fail (EV_IS_WINDOW (ev_window));
3776
3777         update_chrome_flag (ev_window, EV_CHROME_FINDBAR, TRUE);
3778         update_chrome_visibility (ev_window);
3779         gtk_widget_grab_focus (ev_window->priv->find_bar);
3780         ev_view_find_previous (EV_VIEW (ev_window->priv->view));
3781 }
3782
3783 static void
3784 ev_window_cmd_edit_copy (GtkAction *action, EvWindow *ev_window)
3785 {
3786         g_return_if_fail (EV_IS_WINDOW (ev_window));
3787
3788         ev_view_copy (EV_VIEW (ev_window->priv->view));
3789 }
3790
3791 static void
3792 ev_window_sidebar_position_change_cb (GObject    *object,
3793                                       GParamSpec *pspec,
3794                                       EvWindow   *ev_window)
3795 {
3796         if (ev_window->priv->metadata && !ev_window_is_empty (ev_window))
3797                 ev_metadata_set_int (ev_window->priv->metadata, "sidebar_size",
3798                                      gtk_paned_get_position (GTK_PANED (object)));
3799 }
3800
3801 static void
3802 ev_window_update_fullscreen_action (EvWindow *window)
3803 {
3804         GtkAction *action;
3805
3806         action = gtk_action_group_get_action (window->priv->action_group, "ViewFullscreen");
3807         g_signal_handlers_block_by_func
3808                 (action, G_CALLBACK (ev_window_cmd_view_fullscreen), window);
3809         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
3810                                       ev_document_model_get_fullscreen (window->priv->model));
3811         g_signal_handlers_unblock_by_func
3812                 (action, G_CALLBACK (ev_window_cmd_view_fullscreen), window);
3813 }
3814
3815 static void
3816 fullscreen_toolbar_setup_item_properties (GtkUIManager *ui_manager)
3817 {
3818         GtkWidget *item;
3819
3820         item = gtk_ui_manager_get_widget (ui_manager, "/FullscreenToolbar/GoPreviousPage");
3821         g_object_set (item, "is-important", FALSE, NULL);
3822
3823         item = gtk_ui_manager_get_widget (ui_manager, "/FullscreenToolbar/GoNextPage");
3824         g_object_set (item, "is-important", FALSE, NULL);
3825
3826         item = gtk_ui_manager_get_widget (ui_manager, "/FullscreenToolbar/StartPresentation");
3827         g_object_set (item, "is-important", TRUE, NULL);
3828         
3829         item = gtk_ui_manager_get_widget (ui_manager, "/FullscreenToolbar/LeaveFullscreen");
3830         g_object_set (item, "is-important", TRUE, NULL);
3831 }
3832
3833 static void
3834 fullscreen_toolbar_remove_shadow (GtkWidget *toolbar)
3835 {
3836         static gboolean done = FALSE;
3837
3838         if (!done) {
3839                 gtk_rc_parse_string (
3840                         "\n"
3841                         "   style \"fullscreen-toolbar-style\"\n"
3842                         "   {\n"
3843                         "      GtkToolbar::shadow-type=GTK_SHADOW_NONE\n"
3844                         "   }\n"
3845                         "\n"
3846                         "    widget \"*.fullscreen-toolbar\" style \"fullscreen-toolbar-style\"\n"
3847                         "\n");
3848                 done = TRUE;
3849         }
3850         
3851         gtk_widget_set_name (toolbar, "fullscreen-toolbar");
3852 }
3853
3854 static void
3855 ev_window_run_fullscreen (EvWindow *window)
3856 {
3857         gboolean fullscreen_window = TRUE;
3858
3859         if (ev_document_model_get_fullscreen (window->priv->model))
3860                 return;
3861         
3862         if (!window->priv->fullscreen_toolbar) {
3863                 window->priv->fullscreen_toolbar =
3864                         gtk_ui_manager_get_widget (window->priv->ui_manager,
3865                                                    "/FullscreenToolbar");
3866
3867                 gtk_toolbar_set_style (GTK_TOOLBAR (window->priv->fullscreen_toolbar),
3868                                        GTK_TOOLBAR_BOTH_HORIZ);
3869                 fullscreen_toolbar_remove_shadow (window->priv->fullscreen_toolbar);
3870                 fullscreen_toolbar_setup_item_properties (window->priv->ui_manager);
3871
3872                 gtk_box_pack_start (GTK_BOX (window->priv->main_box),
3873                                     window->priv->fullscreen_toolbar,
3874                                     FALSE, FALSE, 0);
3875                 gtk_box_reorder_child (GTK_BOX (window->priv->main_box),
3876                                        window->priv->fullscreen_toolbar, 1);
3877         }
3878
3879         if (EV_WINDOW_IS_PRESENTATION (window)) {
3880                 ev_window_stop_presentation (window, FALSE);
3881                 fullscreen_window = FALSE;
3882         }
3883
3884         g_object_set (G_OBJECT (window->priv->scrolled_window),
3885                       "shadow-type", GTK_SHADOW_NONE,
3886                       NULL);
3887
3888         ev_document_model_set_fullscreen (window->priv->model, TRUE);
3889         ev_window_update_fullscreen_action (window);
3890
3891         /* If the user doesn't have the main toolbar he/she won't probably want
3892          * the toolbar in fullscreen mode. See bug #483048
3893          */
3894         update_chrome_flag (window, EV_CHROME_FULLSCREEN_TOOLBAR,
3895                             (window->priv->chrome & EV_CHROME_TOOLBAR) != 0);
3896         update_chrome_visibility (window);
3897
3898         if (fullscreen_window)
3899                 gtk_window_fullscreen (GTK_WINDOW (window));
3900         gtk_widget_grab_focus (window->priv->view);
3901
3902         if (window->priv->metadata && !ev_window_is_empty (window))
3903                 ev_metadata_set_boolean (window->priv->metadata, "fullscreen", TRUE);
3904 }
3905
3906 static void
3907 ev_window_stop_fullscreen (EvWindow *window,
3908                            gboolean  unfullscreen_window)
3909 {
3910         if (!ev_document_model_get_fullscreen (window->priv->model))
3911                 return;
3912
3913         g_object_set (G_OBJECT (window->priv->scrolled_window),
3914                       "shadow-type", GTK_SHADOW_IN,
3915                       NULL);
3916
3917         ev_document_model_set_fullscreen (window->priv->model, FALSE);
3918         ev_window_update_fullscreen_action (window);
3919         update_chrome_flag (window, EV_CHROME_FULLSCREEN_TOOLBAR, FALSE);
3920         update_chrome_visibility (window);
3921         if (unfullscreen_window)
3922                 gtk_window_unfullscreen (GTK_WINDOW (window));
3923
3924         if (window->priv->metadata && !ev_window_is_empty (window))
3925                 ev_metadata_set_boolean (window->priv->metadata, "fullscreen", FALSE);
3926 }
3927
3928 static void
3929 ev_window_cmd_view_fullscreen (GtkAction *action, EvWindow *window)
3930 {
3931         gboolean fullscreen;
3932
3933         fullscreen = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
3934         if (fullscreen) {
3935                 ev_window_run_fullscreen (window);
3936         } else {
3937                 ev_window_stop_fullscreen (window, TRUE);
3938         }
3939 }
3940
3941 static void
3942 ev_window_update_presentation_action (EvWindow *window)
3943 {
3944         GtkAction *action;
3945
3946         action = gtk_action_group_get_action (window->priv->action_group, "ViewPresentation");
3947         g_signal_handlers_block_by_func
3948                 (action, G_CALLBACK (ev_window_cmd_view_presentation), window);
3949         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
3950                                       EV_WINDOW_IS_PRESENTATION (window));
3951         g_signal_handlers_unblock_by_func
3952                 (action, G_CALLBACK (ev_window_cmd_view_presentation), window);
3953 }
3954
3955 static void
3956 ev_window_view_presentation_finished (EvWindow *window)
3957 {
3958         ev_window_stop_presentation (window, TRUE);
3959 }
3960
3961 static void
3962 ev_window_run_presentation (EvWindow *window)
3963 {
3964         gboolean fullscreen_window = TRUE;
3965         guint    current_page;
3966         guint    rotation;
3967         gboolean inverted_colors;
3968
3969         if (EV_WINDOW_IS_PRESENTATION (window))
3970                 return;
3971
3972         if (ev_document_model_get_fullscreen (window->priv->model)) {
3973                 ev_window_stop_fullscreen (window, FALSE);
3974                 fullscreen_window = FALSE;
3975         }
3976
3977         current_page = ev_document_model_get_page (window->priv->model);
3978         rotation = ev_document_model_get_rotation (window->priv->model);
3979         inverted_colors = ev_document_model_get_inverted_colors (window->priv->model);
3980         window->priv->presentation_view = ev_view_presentation_new (window->priv->document,
3981                                                                     current_page,
3982                                                                     rotation,
3983                                                                     inverted_colors);
3984         g_signal_connect_swapped (window->priv->presentation_view, "finished",
3985                                   G_CALLBACK (ev_window_view_presentation_finished),
3986                                   window);
3987
3988         gtk_box_pack_start (GTK_BOX (window->priv->main_box),
3989                             window->priv->presentation_view,
3990                             TRUE, TRUE, 0);
3991
3992         gtk_widget_hide (window->priv->hpaned);
3993         ev_window_update_presentation_action (window);
3994         update_chrome_visibility (window);
3995
3996         gtk_widget_grab_focus (window->priv->presentation_view);
3997         if (fullscreen_window)
3998                 gtk_window_fullscreen (GTK_WINDOW (window));
3999
4000         gtk_widget_show (window->priv->presentation_view);
4001
4002         ev_application_screensaver_disable (EV_APP);
4003
4004         if (window->priv->metadata && !ev_window_is_empty (window))
4005                 ev_metadata_set_boolean (window->priv->metadata, "presentation", TRUE);
4006 }
4007
4008 static void
4009 ev_window_stop_presentation (EvWindow *window,
4010                              gboolean  unfullscreen_window)
4011 {
4012         guint current_page;
4013
4014         if (!EV_WINDOW_IS_PRESENTATION (window))
4015                 return;
4016
4017         current_page = ev_view_presentation_get_current_page (EV_VIEW_PRESENTATION (window->priv->presentation_view));
4018         ev_document_model_set_page (window->priv->model, current_page);
4019
4020         gtk_container_remove (GTK_CONTAINER (window->priv->main_box),
4021                               window->priv->presentation_view);
4022         window->priv->presentation_view = NULL;
4023
4024         gtk_widget_show (window->priv->hpaned);
4025         ev_window_update_presentation_action (window);
4026         update_chrome_visibility (window);
4027         if (unfullscreen_window)
4028                 gtk_window_unfullscreen (GTK_WINDOW (window));
4029
4030         gtk_widget_grab_focus (window->priv->view);
4031
4032         ev_application_screensaver_enable (EV_APP);
4033
4034         if (window->priv->metadata && !ev_window_is_empty (window))
4035                 ev_metadata_set_boolean (window->priv->metadata, "presentation", FALSE);
4036 }
4037
4038 static void
4039 ev_window_cmd_view_presentation (GtkAction *action, EvWindow *window)
4040 {
4041         gboolean presentation;
4042
4043         presentation = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
4044         if (presentation) {
4045                 ev_window_run_presentation (window);
4046         }
4047 }
4048
4049 static void
4050 ev_window_setup_gtk_settings (EvWindow *window)
4051 {
4052         GtkSettings *settings;
4053         GdkScreen   *screen;
4054         gchar       *menubar_accel_accel;
4055
4056         screen = gtk_window_get_screen (GTK_WINDOW (window));
4057         settings = gtk_settings_get_for_screen (screen);
4058
4059         g_object_get (settings,
4060                       "gtk-menu-bar-accel", &menubar_accel_accel,
4061                       NULL);
4062         if (menubar_accel_accel != NULL && menubar_accel_accel[0] != '\0') {
4063                 gtk_accelerator_parse (menubar_accel_accel,
4064                                        &window->priv->menubar_accel_keyval,
4065                                        &window->priv->menubar_accel_modifier);
4066                 if (window->priv->menubar_accel_keyval == 0) {
4067                         g_warning ("Failed to parse menu bar accelerator '%s'\n",
4068                                    menubar_accel_accel);
4069                 }
4070         } else {
4071                 window->priv->menubar_accel_keyval = 0;
4072                 window->priv->menubar_accel_modifier = 0;
4073         }
4074
4075         g_free (menubar_accel_accel);
4076 }
4077
4078 static void
4079 ev_window_update_max_min_scale (EvWindow *window)
4080 {
4081         gdouble    dpi;
4082         GtkAction *action;
4083         gdouble    min_width, min_height;
4084         gdouble    width, height;
4085         gdouble    max_scale;
4086         gint       rotation = ev_document_model_get_rotation (window->priv->model);
4087
4088         if (!window->priv->document)
4089                 return;
4090
4091         dpi = get_screen_dpi (window) / 72.0;
4092
4093         ev_document_get_min_page_size (window->priv->document, &min_width, &min_height);
4094         width = (rotation == 0 || rotation == 180) ? min_width : min_height;
4095         height = (rotation == 0 || rotation == 180) ? min_height : min_width;
4096         max_scale = sqrt (PAGE_CACHE_SIZE / (width * dpi * 4 * height * dpi));
4097
4098         action = gtk_action_group_get_action (window->priv->action_group,
4099                                               ZOOM_CONTROL_ACTION);
4100         ephy_zoom_action_set_max_zoom_level (EPHY_ZOOM_ACTION (action), max_scale * dpi);
4101
4102         ev_document_model_set_min_scale (window->priv->model, MIN_SCALE * dpi);
4103         ev_document_model_set_max_scale (window->priv->model, max_scale * dpi);
4104 }
4105
4106 static void
4107 ev_window_screen_changed (GtkWidget *widget,
4108                           GdkScreen *old_screen)
4109 {
4110         EvWindow *window = EV_WINDOW (widget);
4111         GdkScreen *screen;
4112
4113         screen = gtk_widget_get_screen (widget);
4114         if (screen == old_screen)
4115                 return;
4116
4117         ev_window_setup_gtk_settings (window);
4118         ev_window_update_max_min_scale (window);
4119
4120         if (GTK_WIDGET_CLASS (ev_window_parent_class)->screen_changed) {
4121                 GTK_WIDGET_CLASS (ev_window_parent_class)->screen_changed (widget, old_screen);
4122         }
4123 }
4124
4125 static gboolean
4126 ev_window_state_event (GtkWidget           *widget,
4127                        GdkEventWindowState *event)
4128 {
4129         EvWindow *window = EV_WINDOW (widget);
4130
4131         if (GTK_WIDGET_CLASS (ev_window_parent_class)->window_state_event) {
4132                 GTK_WIDGET_CLASS (ev_window_parent_class)->window_state_event (widget, event);
4133         }
4134
4135         if ((event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) == 0)
4136                 return FALSE;
4137
4138         if (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) {
4139                 if (ev_document_model_get_fullscreen (window->priv->model) || EV_WINDOW_IS_PRESENTATION (window))
4140                         return FALSE;
4141                 
4142                 ev_window_run_fullscreen (window);
4143         } else {
4144                 if (ev_document_model_get_fullscreen (window->priv->model))
4145                         ev_window_stop_fullscreen (window, FALSE);
4146                 else if (EV_WINDOW_IS_PRESENTATION (window))
4147                         ev_window_stop_presentation (window, FALSE);
4148         }
4149
4150         return FALSE;
4151 }
4152
4153 static void
4154 ev_window_set_page_mode (EvWindow         *window,
4155                          EvWindowPageMode  page_mode)
4156 {
4157         GtkWidget *child = NULL;
4158         GtkWidget *real_child;
4159
4160         if (window->priv->page_mode == page_mode)
4161                 return;
4162
4163         window->priv->page_mode = page_mode;
4164
4165         switch (page_mode) {
4166                 case PAGE_MODE_DOCUMENT:
4167                         child = window->priv->view;
4168                         break;
4169                 case PAGE_MODE_PASSWORD:
4170                         child = window->priv->password_view;
4171                         break;
4172                 default:
4173                         g_assert_not_reached ();
4174         }
4175
4176         real_child = gtk_bin_get_child (GTK_BIN (window->priv->scrolled_window));
4177         if (child != real_child) {
4178                 gtk_container_remove (GTK_CONTAINER (window->priv->scrolled_window),
4179                                       real_child);
4180                 gtk_container_add (GTK_CONTAINER (window->priv->scrolled_window),
4181                                    child);
4182         }
4183         ev_window_update_actions (window);
4184 }
4185
4186
4187 static void
4188 ev_window_cmd_edit_rotate_left (GtkAction *action, EvWindow *ev_window)
4189 {
4190         gint rotation = ev_document_model_get_rotation (ev_window->priv->model);
4191
4192         ev_document_model_set_rotation (ev_window->priv->model, rotation - 90);
4193 }
4194
4195 static void
4196 ev_window_cmd_edit_rotate_right (GtkAction *action, EvWindow *ev_window)
4197 {
4198         gint rotation = ev_document_model_get_rotation (ev_window->priv->model);
4199
4200         ev_document_model_set_rotation (ev_window->priv->model, rotation + 90);
4201 }
4202
4203 static void
4204 ev_window_cmd_view_inverted_colors (GtkAction *action, EvWindow *ev_window)
4205 {
4206         gboolean inverted_colors = ev_document_model_get_inverted_colors (ev_window->priv->model);
4207
4208         ev_document_model_set_inverted_colors (ev_window->priv->model, !inverted_colors);
4209 }
4210
4211 static void
4212 ev_window_cmd_edit_toolbar_cb (GtkDialog *dialog,
4213                                gint       response,
4214                                EvWindow  *ev_window)
4215 {
4216         EggEditableToolbar *toolbar;
4217         gchar              *toolbars_file;
4218
4219         toolbar = EGG_EDITABLE_TOOLBAR (ev_window->priv->toolbar);
4220         egg_editable_toolbar_set_edit_mode (toolbar, FALSE);
4221
4222         toolbars_file = g_build_filename (ev_application_get_dot_dir (EV_APP, TRUE),
4223                                           "evince_toolbar.xml", NULL);
4224         egg_toolbars_model_save_toolbars (egg_editable_toolbar_get_model (toolbar),
4225                                           toolbars_file, "1.0");
4226         g_free (toolbars_file);
4227
4228         gtk_widget_destroy (GTK_WIDGET (dialog));
4229 }
4230
4231 static void
4232 ev_window_cmd_edit_toolbar (GtkAction *action, EvWindow *ev_window)
4233 {
4234         GtkWidget          *dialog;
4235         GtkWidget          *editor;
4236         GtkWidget          *content_area;
4237         EggEditableToolbar *toolbar;
4238
4239         dialog = gtk_dialog_new_with_buttons (_("Toolbar Editor"),
4240                                               GTK_WINDOW (ev_window),
4241                                               GTK_DIALOG_DESTROY_WITH_PARENT,
4242                                               GTK_STOCK_CLOSE,
4243                                               GTK_RESPONSE_CLOSE,
4244                                               NULL);
4245         content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
4246         gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
4247         gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)), 5);
4248         gtk_box_set_spacing (GTK_BOX (content_area), 2);
4249         gtk_window_set_default_size (GTK_WINDOW (dialog), 500, 400);
4250
4251         toolbar = EGG_EDITABLE_TOOLBAR (ev_window->priv->toolbar);
4252         editor = egg_toolbar_editor_new (ev_window->priv->ui_manager,
4253                                          egg_editable_toolbar_get_model (toolbar));
4254
4255         gtk_container_set_border_width (GTK_CONTAINER (editor), 5);
4256         gtk_box_set_spacing (GTK_BOX (EGG_TOOLBAR_EDITOR (editor)), 5);
4257
4258         gtk_container_add (GTK_CONTAINER (content_area), editor);
4259
4260         egg_editable_toolbar_set_edit_mode (toolbar, TRUE);
4261
4262         g_signal_connect (dialog, "response",
4263                           G_CALLBACK (ev_window_cmd_edit_toolbar_cb),
4264                           ev_window);
4265         gtk_widget_show_all (dialog);
4266 }
4267
4268 static void
4269 ev_window_cmd_edit_save_settings (GtkAction *action, EvWindow *ev_window)
4270 {
4271         EvWindowPrivate *priv = ev_window->priv;
4272         EvDocumentModel *model = priv->model;
4273         GSettings       *settings = priv->default_settings;
4274
4275         g_settings_set_boolean (settings, "continuous",
4276                                 ev_document_model_get_continuous (model));
4277         g_settings_set_boolean (settings, "dual-page",
4278                                 ev_document_model_get_dual_page (model));
4279         g_settings_set_boolean (settings, "fullscreen",
4280                                 ev_document_model_get_fullscreen (model));
4281         g_settings_set_boolean (settings, "inverted-colors",
4282                                 ev_document_model_get_inverted_colors (model));
4283         g_settings_set_enum (settings, "sizing-mode",
4284                              ev_document_model_get_sizing_mode (model));
4285         g_settings_set_boolean (settings, "show-toolbar",
4286                                 gtk_widget_get_visible (priv->toolbar));
4287         g_settings_set_boolean (settings, "show-sidebar",
4288                                 gtk_widget_get_visible (priv->sidebar));
4289         g_settings_set_int (settings, "sidebar-size",
4290                             gtk_paned_get_position (GTK_PANED (priv->hpaned)));
4291         g_settings_set_string (settings, "sidebar-page",
4292                                ev_window_sidebar_get_current_page_id (ev_window));
4293         g_settings_apply (settings);
4294 }
4295
4296 static void
4297 ev_window_cmd_view_zoom_in (GtkAction *action, EvWindow *ev_window)
4298 {
4299         g_return_if_fail (EV_IS_WINDOW (ev_window));
4300
4301         ev_document_model_set_sizing_mode (ev_window->priv->model, EV_SIZING_FREE);
4302         ev_view_zoom_in (EV_VIEW (ev_window->priv->view));
4303 }
4304
4305 static void
4306 ev_window_cmd_view_zoom_out (GtkAction *action, EvWindow *ev_window)
4307 {
4308         g_return_if_fail (EV_IS_WINDOW (ev_window));
4309
4310         ev_document_model_set_sizing_mode (ev_window->priv->model, EV_SIZING_FREE);
4311         ev_view_zoom_out (EV_VIEW (ev_window->priv->view));
4312 }
4313
4314 static void
4315 ev_window_cmd_go_previous_page (GtkAction *action, EvWindow *ev_window)
4316 {
4317         g_return_if_fail (EV_IS_WINDOW (ev_window));
4318
4319         ev_view_previous_page (EV_VIEW (ev_window->priv->view));
4320 }
4321
4322 static void
4323 ev_window_cmd_go_next_page (GtkAction *action, EvWindow *ev_window)
4324 {
4325         g_return_if_fail (EV_IS_WINDOW (ev_window));
4326
4327         ev_view_next_page (EV_VIEW (ev_window->priv->view));
4328 }
4329
4330 static void
4331 ev_window_cmd_go_first_page (GtkAction *action, EvWindow *ev_window)
4332 {
4333         g_return_if_fail (EV_IS_WINDOW (ev_window));
4334
4335         ev_document_model_set_page (ev_window->priv->model, 0);
4336 }
4337
4338 static void
4339 ev_window_cmd_go_last_page (GtkAction *action, EvWindow *ev_window)
4340 {
4341         g_return_if_fail (EV_IS_WINDOW (ev_window));
4342
4343         ev_document_model_set_page (ev_window->priv->model,
4344                                     ev_document_get_n_pages (ev_window->priv->document) - 1);
4345 }
4346
4347 static void
4348 ev_window_cmd_go_forward (GtkAction *action, EvWindow *ev_window)
4349 {
4350         int n_pages, current_page;
4351         
4352         g_return_if_fail (EV_IS_WINDOW (ev_window));
4353
4354         n_pages = ev_document_get_n_pages (ev_window->priv->document);
4355         current_page = ev_document_model_get_page (ev_window->priv->model);
4356         
4357         if (current_page + 10 < n_pages) {
4358                 ev_document_model_set_page (ev_window->priv->model, current_page + 10);
4359         }
4360 }
4361
4362 static void
4363 ev_window_cmd_go_backward (GtkAction *action, EvWindow *ev_window)
4364 {
4365         int current_page;
4366         
4367         g_return_if_fail (EV_IS_WINDOW (ev_window));
4368
4369         current_page = ev_document_model_get_page (ev_window->priv->model);
4370         
4371         if (current_page - 10 >= 0) {
4372                 ev_document_model_set_page (ev_window->priv->model, current_page - 10);
4373         }
4374 }
4375
4376 static void
4377 ev_window_cmd_bookmark_activate (GtkAction *action,
4378                                  EvWindow  *window)
4379 {
4380         guint page = ev_bookmark_action_get_page (EV_BOOKMARK_ACTION (action));
4381
4382         ev_document_model_set_page (window->priv->model, page);
4383 }
4384
4385 static gint
4386 compare_bookmarks (EvBookmark *a,
4387                    EvBookmark *b)
4388 {
4389         return strcmp (a->title, b->title);
4390 }
4391
4392 static void
4393 ev_window_setup_bookmarks (EvWindow *window)
4394 {
4395         GList *items, *l;
4396
4397         if (!window->priv->bookmarks)
4398                 return;
4399
4400         if (window->priv->bookmarks_ui_id > 0) {
4401                 gtk_ui_manager_remove_ui (window->priv->ui_manager,
4402                                           window->priv->bookmarks_ui_id);
4403                 gtk_ui_manager_ensure_update (window->priv->ui_manager);
4404         }
4405         window->priv->bookmarks_ui_id = gtk_ui_manager_new_merge_id (window->priv->ui_manager);
4406
4407         if (window->priv->bookmarks_action_group) {
4408                 gtk_ui_manager_remove_action_group (window->priv->ui_manager,
4409                                                     window->priv->bookmarks_action_group);
4410                 g_object_unref (window->priv->bookmarks_action_group);
4411         }
4412         window->priv->bookmarks_action_group = gtk_action_group_new ("BookmarksActions");
4413         gtk_ui_manager_insert_action_group (window->priv->ui_manager,
4414                                             window->priv->bookmarks_action_group, -1);
4415
4416         items = ev_bookmarks_get_bookmarks (window->priv->bookmarks);
4417         items = g_list_sort (items, (GCompareFunc)compare_bookmarks);
4418
4419         for (l = items; l && l->data; l = g_list_next (l)) {
4420                 EvBookmark *bm = (EvBookmark *)l->data;
4421                 GtkAction  *action;
4422
4423                 action = ev_bookmark_action_new (bm);
4424                 g_signal_connect (action, "activate",
4425                                   G_CALLBACK (ev_window_cmd_bookmark_activate),
4426                                   window);
4427                 gtk_action_group_add_action (window->priv->bookmarks_action_group,
4428                                              action);
4429
4430                 gtk_ui_manager_add_ui (window->priv->ui_manager,
4431                                        window->priv->bookmarks_ui_id,
4432                                        "/MainMenu/BookmarksMenu/BookmarksItems",
4433                                        gtk_action_get_label (action),
4434                                        gtk_action_get_name (action),
4435                                        GTK_UI_MANAGER_MENUITEM,
4436                                        FALSE);
4437
4438                 g_object_unref (action);
4439         }
4440
4441         g_list_free (items);
4442 }
4443
4444 static void
4445 ev_window_cmd_bookmarks_add (GtkAction *action,
4446                              EvWindow  *window)
4447 {
4448         EvBookmark bm;
4449         gchar     *page_label;
4450         gchar     *page_title;
4451
4452         bm.page = ev_document_model_get_page (window->priv->model);
4453         page_label = ev_document_get_page_label (window->priv->document, bm.page);
4454         page_title = ev_window_get_page_title (window, page_label);
4455         bm.title = page_title ? page_title : g_strdup_printf (_("Page %s"), page_label);
4456         g_free (page_label);
4457
4458         /* EvBookmarks takes ownership of bookmark */
4459         ev_bookmarks_add (window->priv->bookmarks, &bm);
4460 }
4461
4462 static void
4463 ev_window_cmd_view_reload (GtkAction *action, EvWindow *ev_window)
4464 {
4465         ev_window_reload_document (ev_window, NULL);
4466 }
4467
4468 static void
4469 ev_window_cmd_view_autoscroll (GtkAction *action, EvWindow *ev_window)
4470 {
4471         ev_view_autoscroll_start (EV_VIEW (ev_window->priv->view));
4472 }
4473
4474 #if OFFLINE_HELP_ENABLED
4475 #define EV_HELP "ghelp:evince"
4476 #else
4477 #define EV_HELP "http://library.gnome.org/users/evince/stable/"
4478 #endif
4479
4480 static void
4481 ev_window_cmd_help_contents (GtkAction *action, EvWindow *ev_window)
4482 {
4483         GError  *error = NULL;
4484
4485         gtk_show_uri (gtk_window_get_screen (GTK_WINDOW (ev_window)),
4486                       EV_HELP,
4487                       gtk_get_current_event_time (),
4488                       &error);
4489         if (error) {
4490                 ev_window_error_message (ev_window, error, 
4491                                          "%s", _("There was an error displaying help"));
4492                 g_error_free (error);
4493         }
4494 }
4495
4496 static void
4497 ev_window_cmd_leave_fullscreen (GtkAction *action, EvWindow *window)
4498 {
4499         ev_window_stop_fullscreen (window, TRUE);
4500 }
4501
4502 static void
4503 ev_window_cmd_start_presentation (GtkAction *action, EvWindow *window)
4504 {
4505         ev_window_run_presentation (window);
4506 }
4507
4508 static void
4509 ev_window_cmd_escape (GtkAction *action, EvWindow *window)
4510 {
4511         GtkWidget *widget;
4512
4513         ev_view_autoscroll_stop (EV_VIEW (window->priv->view));
4514         
4515         widget = gtk_window_get_focus (GTK_WINDOW (window));
4516         if (widget && gtk_widget_get_ancestor (widget, EGG_TYPE_FIND_BAR)) {
4517                 update_chrome_flag (window, EV_CHROME_FINDBAR, FALSE);
4518                 update_chrome_visibility (window);
4519                 gtk_widget_grab_focus (window->priv->view);
4520         } else {
4521                 gboolean fullscreen;
4522
4523                 fullscreen = ev_document_model_get_fullscreen (window->priv->model);
4524
4525                 if (fullscreen) {
4526                         ev_window_stop_fullscreen (window, TRUE);
4527                 } else if (EV_WINDOW_IS_PRESENTATION (window)) {
4528                         ev_window_stop_presentation (window, TRUE);
4529                         gtk_widget_grab_focus (window->priv->view);
4530                 } else {
4531                         gtk_widget_grab_focus (window->priv->view);
4532                 }
4533
4534                 if (fullscreen && EV_WINDOW_IS_PRESENTATION (window))
4535                         g_warning ("Both fullscreen and presentation set somehow");
4536         }
4537 }
4538
4539 static void
4540 save_sizing_mode (EvWindow *window)
4541 {
4542         EvSizingMode mode;
4543         GEnumValue *enum_value;
4544
4545         if (!window->priv->metadata || ev_window_is_empty (window))
4546                 return;
4547
4548         mode = ev_document_model_get_sizing_mode (window->priv->model);
4549         enum_value = g_enum_get_value (g_type_class_peek (EV_TYPE_SIZING_MODE), mode);
4550         ev_metadata_set_string (window->priv->metadata, "sizing_mode",
4551                                 enum_value->value_nick);
4552 }
4553
4554 static void
4555 ev_window_document_changed_cb (EvDocumentModel *model,
4556                                GParamSpec      *pspec,
4557                                EvWindow        *ev_window)
4558 {
4559         ev_window_set_document (ev_window,
4560                                 ev_document_model_get_document (model));
4561 }
4562
4563 static void
4564 ev_window_sizing_mode_changed_cb (EvDocumentModel *model,
4565                                   GParamSpec      *pspec,
4566                                   EvWindow        *ev_window)
4567 {
4568         EvSizingMode sizing_mode = ev_document_model_get_sizing_mode (model);
4569
4570         g_object_set (ev_window->priv->scrolled_window,
4571                       "hscrollbar-policy",
4572                       sizing_mode == EV_SIZING_FREE ?
4573                       GTK_POLICY_AUTOMATIC : GTK_POLICY_NEVER,
4574                       "vscrollbar-policy", GTK_POLICY_AUTOMATIC,
4575                       NULL);
4576
4577         update_sizing_buttons (ev_window);
4578         save_sizing_mode (ev_window);
4579 }
4580
4581 static void
4582 ev_window_zoom_changed_cb (EvDocumentModel *model, GParamSpec *pspec, EvWindow *ev_window)
4583 {
4584         ev_window_update_actions (ev_window);
4585
4586         if (!ev_window->priv->metadata)
4587                 return;
4588
4589         if (ev_document_model_get_sizing_mode (model) == EV_SIZING_FREE && !ev_window_is_empty (ev_window)) {
4590                 gdouble zoom;
4591
4592                 zoom = ev_document_model_get_scale (model);
4593                 zoom *= 72.0 / get_screen_dpi (ev_window);
4594                 ev_metadata_set_double (ev_window->priv->metadata, "zoom", zoom);
4595         }
4596 }
4597
4598 static void
4599 ev_window_update_continuous_action (EvWindow *window)
4600 {
4601         GtkAction *action;
4602
4603         action = gtk_action_group_get_action (window->priv->action_group, "ViewContinuous");
4604         g_signal_handlers_block_by_func
4605                 (action, G_CALLBACK (ev_window_cmd_continuous), window);
4606         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
4607                                       ev_document_model_get_continuous (window->priv->model));
4608         g_signal_handlers_unblock_by_func
4609                 (action, G_CALLBACK (ev_window_cmd_continuous), window);
4610 }
4611
4612 static void
4613 ev_window_update_dual_page_action (EvWindow *window)
4614 {
4615         GtkAction *action;
4616
4617         action = gtk_action_group_get_action (window->priv->action_group, "ViewDual");
4618         g_signal_handlers_block_by_func
4619                 (action, G_CALLBACK (ev_window_cmd_dual), window);
4620         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
4621                                       ev_document_model_get_dual_page (window->priv->model));
4622         g_signal_handlers_unblock_by_func
4623                 (action, G_CALLBACK (ev_window_cmd_dual), window);
4624 }
4625
4626 static void
4627 ev_window_continuous_changed_cb (EvDocumentModel *model,
4628                                  GParamSpec      *pspec,
4629                                  EvWindow        *ev_window)
4630 {
4631         ev_window_update_continuous_action (ev_window);
4632
4633         if (ev_window->priv->metadata && !ev_window_is_empty (ev_window))
4634                 ev_metadata_set_boolean (ev_window->priv->metadata, "continuous",
4635                                          ev_document_model_get_continuous (model));
4636 }
4637
4638 static void
4639 ev_window_rotation_changed_cb (EvDocumentModel *model,
4640                                GParamSpec      *pspec,
4641                                EvWindow        *window)
4642 {
4643         gint rotation = ev_document_model_get_rotation (model);
4644
4645         if (window->priv->metadata && !ev_window_is_empty (window))
4646                 ev_metadata_set_int (window->priv->metadata, "rotation",
4647                                      rotation);
4648
4649         ev_window_update_max_min_scale (window);
4650         ev_window_refresh_window_thumbnail (window);
4651 }
4652
4653 static void
4654 ev_window_update_inverted_colors_action (EvWindow *window)
4655 {
4656         GtkAction *action;
4657
4658         action = gtk_action_group_get_action (window->priv->action_group, "ViewInvertedColors");
4659         g_signal_handlers_block_by_func
4660                 (action, G_CALLBACK (ev_window_cmd_view_inverted_colors), window);
4661         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
4662                                       ev_document_model_get_inverted_colors (window->priv->model));
4663         g_signal_handlers_unblock_by_func
4664                 (action, G_CALLBACK (ev_window_cmd_view_inverted_colors), window);
4665 }
4666
4667 static void
4668 ev_window_inverted_colors_changed_cb (EvDocumentModel *model,
4669                                       GParamSpec      *pspec,
4670                                       EvWindow        *window)
4671 {
4672         gboolean inverted_colors = ev_document_model_get_inverted_colors (model);
4673
4674         ev_window_update_inverted_colors_action (window);
4675
4676         if (window->priv->metadata && !ev_window_is_empty (window))
4677                 ev_metadata_set_boolean (window->priv->metadata, "inverted-colors",
4678                                          inverted_colors);
4679
4680         ev_window_refresh_window_thumbnail (window);
4681 }
4682
4683 static void
4684 ev_window_dual_mode_changed_cb (EvDocumentModel *model,
4685                                 GParamSpec      *pspec,
4686                                 EvWindow        *ev_window)
4687 {
4688         ev_window_update_dual_page_action (ev_window);
4689
4690         if (ev_window->priv->metadata && !ev_window_is_empty (ev_window))
4691                 ev_metadata_set_boolean (ev_window->priv->metadata, "dual-page",
4692                                          ev_document_model_get_dual_page (model));
4693 }
4694
4695 static char *
4696 build_comments_string (EvDocument *document)
4697 {
4698         gchar *comments = NULL;
4699         EvDocumentBackendInfo info;
4700
4701         if (document && ev_document_get_backend_info (document, &info)) {
4702                 comments = g_strdup_printf (
4703                         _("Document Viewer\nUsing %s (%s)"),
4704                         info.name, info.version);
4705         } else {
4706                 comments = g_strdup_printf (
4707                         _("Document Viewer"));
4708         }
4709
4710         return comments;
4711 }
4712
4713 static void
4714 ev_window_cmd_help_about (GtkAction *action, EvWindow *ev_window)
4715 {
4716         const char *authors[] = {
4717                 "Martin Kretzschmar <m_kretzschmar@gmx.net>",
4718                 "Jonathan Blandford <jrb@gnome.org>",
4719                 "Marco Pesenti Gritti <marco@gnome.org>",
4720                 "Nickolay V. Shmyrev <nshmyrev@yandex.ru>",
4721                 "Bryan Clark <clarkbw@gnome.org>",
4722                 "Carlos Garcia Campos <carlosgc@gnome.org>",
4723                 "Wouter Bolsterlee <wbolster@gnome.org>",
4724                 "Christian Persch <chpe" "\100" "gnome.org>",
4725                 NULL
4726         };
4727
4728         const char *documenters[] = {
4729                 "Nickolay V. Shmyrev <nshmyrev@yandex.ru>",
4730                 NULL
4731         };
4732
4733         const char *license[] = {
4734                 N_("Evince is free software; you can redistribute it and/or modify "
4735                    "it under the terms of the GNU General Public License as published by "
4736                    "the Free Software Foundation; either version 2 of the License, or "
4737                    "(at your option) any later version.\n"),
4738                 N_("Evince is distributed in the hope that it will be useful, "
4739                    "but WITHOUT ANY WARRANTY; without even the implied warranty of "
4740                    "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the "
4741                    "GNU General Public License for more details.\n"),
4742                 N_("You should have received a copy of the GNU General Public License "
4743                    "along with Evince; if not, write to the Free Software Foundation, Inc., "
4744                    "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA\n")
4745         };
4746
4747         char *license_trans;
4748         char *comments;
4749
4750 #ifdef ENABLE_NLS
4751         const char **p;
4752
4753         for (p = authors; *p; ++p)
4754                 *p = _(*p);
4755
4756         for (p = documenters; *p; ++p)
4757                 *p = _(*p);
4758 #endif
4759
4760         license_trans = g_strconcat (_(license[0]), "\n", _(license[1]), "\n",
4761                                      _(license[2]), "\n", NULL);
4762
4763         comments = build_comments_string (ev_window->priv->document);
4764
4765         gtk_show_about_dialog (
4766                 GTK_WINDOW (ev_window),
4767                 "name", _("Evince"),
4768                 "version", VERSION,
4769                 "copyright",
4770                 _("© 1996–2010 The Evince authors"),
4771                 "license", license_trans,
4772                 "website", "http://www.gnome.org/projects/evince",
4773                 "comments", comments,
4774                 "authors", authors,
4775                 "documenters", documenters,
4776                 "translator-credits", _("translator-credits"),
4777                 "logo-icon-name", "evince",
4778                 "wrap-license", TRUE,
4779                 NULL);
4780
4781         g_free (comments);
4782         g_free (license_trans);
4783 }
4784
4785 static void
4786 ev_window_view_toolbar_cb (GtkAction *action, EvWindow *ev_window)
4787 {
4788         gboolean active;
4789         
4790         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
4791         update_chrome_flag (ev_window, EV_CHROME_TOOLBAR, active);
4792         update_chrome_visibility (ev_window);
4793         if (ev_window->priv->metadata)
4794                 ev_metadata_set_boolean (ev_window->priv->metadata, "show_toolbar", active);
4795 }
4796
4797 static void
4798 ev_window_view_sidebar_cb (GtkAction *action, EvWindow *ev_window)
4799 {
4800         if (EV_WINDOW_IS_PRESENTATION (ev_window))
4801                 return;
4802             
4803         update_chrome_flag (ev_window, EV_CHROME_SIDEBAR,
4804                             gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
4805         update_chrome_visibility (ev_window);
4806 }
4807
4808 static void
4809 ev_window_sidebar_current_page_changed_cb (EvSidebar  *ev_sidebar,
4810                                            GParamSpec *pspec,
4811                                            EvWindow   *ev_window)
4812 {
4813         if (ev_window->priv->metadata && !ev_window_is_empty (ev_window)) {
4814                 ev_metadata_set_string (ev_window->priv->metadata,
4815                                         "sidebar_page",
4816                                         ev_window_sidebar_get_current_page_id (ev_window));
4817         }
4818 }
4819
4820 static void
4821 ev_window_sidebar_visibility_changed_cb (EvSidebar  *ev_sidebar,
4822                                          GParamSpec *pspec,
4823                                          EvWindow   *ev_window)
4824 {
4825         GtkAction *action;
4826
4827         action = gtk_action_group_get_action (ev_window->priv->action_group, "ViewSidebar");
4828
4829         if (!EV_WINDOW_IS_PRESENTATION (ev_window)) {
4830                 gboolean visible = gtk_widget_get_visible (GTK_WIDGET (ev_sidebar));
4831
4832                 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), visible);
4833
4834                 if (ev_window->priv->metadata)
4835                         ev_metadata_set_boolean (ev_window->priv->metadata, "sidebar_visibility",
4836                                                  visible);
4837         }
4838 }
4839
4840 static void
4841 view_menu_link_popup (EvWindow *ev_window,
4842                       EvLink   *link)
4843 {
4844         gboolean   show_external = FALSE;
4845         gboolean   show_internal = FALSE;
4846         GtkAction *action;
4847         
4848         if (ev_window->priv->link)
4849                 g_object_unref (ev_window->priv->link);
4850         
4851         if (link)
4852                 ev_window->priv->link = g_object_ref (link);
4853         else    
4854                 ev_window->priv->link = NULL;
4855
4856         if (ev_window->priv->link) {
4857                 EvLinkAction *ev_action;
4858
4859                 ev_action = ev_link_get_action (link);
4860                 if (ev_action) {
4861                         switch (ev_link_action_get_action_type (ev_action)) {
4862                                 case EV_LINK_ACTION_TYPE_GOTO_DEST:
4863                                 case EV_LINK_ACTION_TYPE_GOTO_REMOTE:
4864                                         show_internal = TRUE;
4865                                         break;
4866                                 case EV_LINK_ACTION_TYPE_EXTERNAL_URI:
4867                                 case EV_LINK_ACTION_TYPE_LAUNCH:
4868                                         show_external = TRUE;
4869                                         break;
4870                                 default:
4871                                         break;
4872                         }
4873                 }
4874         }
4875         
4876         action = gtk_action_group_get_action (ev_window->priv->view_popup_action_group,
4877                                               "OpenLink");
4878         gtk_action_set_visible (action, show_external);
4879
4880         action = gtk_action_group_get_action (ev_window->priv->view_popup_action_group,
4881                                               "CopyLinkAddress");
4882         gtk_action_set_visible (action, show_external);
4883
4884         action = gtk_action_group_get_action (ev_window->priv->view_popup_action_group,
4885                                               "GoLink");
4886         gtk_action_set_visible (action, show_internal);
4887
4888         action = gtk_action_group_get_action (ev_window->priv->view_popup_action_group,
4889                                               "OpenLinkNewWindow");
4890         gtk_action_set_visible (action, show_internal);
4891 }
4892
4893 static void
4894 view_menu_image_popup (EvWindow  *ev_window,
4895                        EvImage   *image)
4896 {
4897         GtkAction *action;
4898         gboolean   show_image = FALSE;
4899         
4900         if (ev_window->priv->image)
4901                 g_object_unref (ev_window->priv->image);
4902         
4903         if (image)
4904                 ev_window->priv->image = g_object_ref (image);
4905         else    
4906                 ev_window->priv->image = NULL;
4907
4908         show_image = (ev_window->priv->image != NULL);
4909         
4910         action = gtk_action_group_get_action (ev_window->priv->view_popup_action_group,
4911                                               "SaveImageAs");
4912         gtk_action_set_visible (action, show_image);
4913
4914         action = gtk_action_group_get_action (ev_window->priv->view_popup_action_group,
4915                                               "CopyImage");
4916         gtk_action_set_visible (action, show_image);
4917 }
4918
4919 static void
4920 view_menu_annot_popup (EvWindow     *ev_window,
4921                        EvAnnotation *annot)
4922 {
4923         GtkAction *action;
4924         gboolean   show_annot = FALSE;
4925
4926         if (ev_window->priv->annot)
4927                 g_object_unref (ev_window->priv->annot);
4928         ev_window->priv->annot = (annot) ? g_object_ref (annot) : NULL;
4929
4930         action = gtk_action_group_get_action (ev_window->priv->view_popup_action_group,
4931                                               "AnnotProperties");
4932         gtk_action_set_visible (action, (annot != NULL && EV_IS_ANNOTATION_MARKUP (annot)));
4933
4934         if (annot && EV_IS_ANNOTATION_ATTACHMENT (annot)) {
4935                 EvAttachment *attachment;
4936
4937                 attachment = ev_annotation_attachment_get_attachment (EV_ANNOTATION_ATTACHMENT (annot));
4938                 if (attachment) {
4939                         show_annot = TRUE;
4940                         if (ev_window->priv->attach_list) {
4941                                 g_list_foreach (ev_window->priv->attach_list,
4942                                                 (GFunc) g_object_unref, NULL);
4943                                 g_list_free (ev_window->priv->attach_list);
4944                                 ev_window->priv->attach_list = NULL;
4945                         }
4946                         ev_window->priv->attach_list =
4947                                 g_list_prepend (ev_window->priv->attach_list,
4948                                                 g_object_ref (attachment));
4949                 }
4950         }
4951
4952         action = gtk_action_group_get_action (ev_window->priv->attachment_popup_action_group,
4953                                               "OpenAttachment");
4954         gtk_action_set_visible (action, show_annot);
4955
4956         action = gtk_action_group_get_action (ev_window->priv->attachment_popup_action_group,
4957                                               "SaveAttachmentAs");
4958         gtk_action_set_visible (action, show_annot);
4959 }
4960
4961 static gboolean
4962 view_menu_popup_cb (EvView   *view,
4963                     GList    *items,
4964                     EvWindow *ev_window)
4965 {
4966         GList   *l;
4967         gboolean has_link = FALSE;
4968         gboolean has_image = FALSE;
4969         gboolean has_annot = FALSE;
4970
4971         for (l = items; l; l = g_list_next (l)) {
4972                 if (EV_IS_LINK (l->data)) {
4973                         view_menu_link_popup (ev_window, EV_LINK (l->data));
4974                         has_link = TRUE;
4975                 } else if (EV_IS_IMAGE (l->data)) {
4976                         view_menu_image_popup (ev_window, EV_IMAGE (l->data));
4977                         has_image = TRUE;
4978                 } else if (EV_IS_ANNOTATION (l->data)) {
4979                         view_menu_annot_popup (ev_window, EV_ANNOTATION (l->data));
4980                         has_annot = TRUE;
4981                 }
4982         }
4983
4984         if (!has_link)
4985                 view_menu_link_popup (ev_window, NULL);
4986         if (!has_image)
4987                 view_menu_image_popup (ev_window, NULL);
4988         if (!has_annot)
4989                 view_menu_annot_popup (ev_window, NULL);
4990
4991         gtk_menu_popup (GTK_MENU (ev_window->priv->view_popup),
4992                         NULL, NULL, NULL, NULL,
4993                         3, gtk_get_current_event_time ());
4994         return TRUE;
4995 }
4996
4997 static gboolean
4998 attachment_bar_menu_popup_cb (EvSidebarAttachments *attachbar,
4999                               GList           *attach_list,
5000                               EvWindow        *ev_window)
5001 {
5002         GtkWidget *popup;
5003
5004         g_assert (attach_list != NULL);
5005
5006         if (ev_window->priv->attach_list) {
5007                 g_list_foreach (ev_window->priv->attach_list,
5008                                 (GFunc) g_object_unref, NULL);
5009                 g_list_free (ev_window->priv->attach_list);
5010         }
5011         
5012         ev_window->priv->attach_list = attach_list;
5013         
5014         popup = ev_window->priv->attachment_popup;
5015
5016         gtk_menu_popup (GTK_MENU (popup), NULL, NULL,
5017                         NULL, NULL,
5018                         3, gtk_get_current_event_time ());
5019
5020         return TRUE;
5021 }
5022
5023 static void
5024 ev_window_update_find_status_message (EvWindow *ev_window)
5025 {
5026         gchar *message;
5027
5028         if (!ev_window->priv->find_job)
5029                 return;
5030         
5031         if (ev_job_is_finished (ev_window->priv->find_job)) {
5032                 EvJobFind *job_find = EV_JOB_FIND (ev_window->priv->find_job);
5033
5034                 if (ev_job_find_has_results (job_find)) {
5035                         gint n_results;
5036
5037                         n_results = ev_job_find_get_n_results (job_find,
5038                                                                ev_document_model_get_page (ev_window->priv->model));
5039                         /* TRANS: Sometimes this could be better translated as
5040                            "%d hit(s) on this page".  Therefore this string
5041                            contains plural cases. */
5042                         message = g_strdup_printf (ngettext ("%d found on this page",
5043                                                              "%d found on this page",
5044                                                              n_results),
5045                                                    n_results);
5046                 } else {
5047                         message = g_strdup (_("Not found"));
5048                 }
5049         } else {
5050                 gdouble percent;
5051
5052                 percent = ev_job_find_get_progress (EV_JOB_FIND (ev_window->priv->find_job));
5053                 message = g_strdup_printf (_("%3d%% remaining to search"),
5054                                            (gint) ((1.0 - percent) * 100));
5055         }
5056         
5057         egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar), message);
5058         g_free (message);
5059 }
5060
5061 static void
5062 ev_window_find_job_finished_cb (EvJobFind *job,
5063                                 EvWindow  *ev_window)
5064 {
5065         ev_window_update_find_status_message (ev_window);
5066 }
5067
5068 static void
5069 ev_window_find_job_updated_cb (EvJobFind *job,
5070                                gint       page,
5071                                EvWindow  *ev_window)
5072 {
5073         ev_window_update_actions (ev_window);
5074         
5075         ev_view_find_changed (EV_VIEW (ev_window->priv->view),
5076                               ev_job_find_get_results (job),
5077                               page);
5078         ev_window_update_find_status_message (ev_window);
5079 }
5080
5081 static void
5082 ev_window_clear_find_job (EvWindow *ev_window)
5083 {
5084         if (ev_window->priv->find_job != NULL) {
5085                 if (!ev_job_is_finished (ev_window->priv->find_job))
5086                         ev_job_cancel (ev_window->priv->find_job);
5087
5088                 g_signal_handlers_disconnect_by_func (ev_window->priv->find_job,
5089                                                       ev_window_find_job_finished_cb,
5090                                                       ev_window);
5091                 g_signal_handlers_disconnect_by_func (ev_window->priv->find_job,
5092                                                       ev_window_find_job_updated_cb,
5093                                                       ev_window);
5094                 g_object_unref (ev_window->priv->find_job);
5095                 ev_window->priv->find_job = NULL;
5096         }
5097 }
5098
5099 static void
5100 find_bar_previous_cb (EggFindBar *find_bar,
5101                       EvWindow   *ev_window)
5102 {
5103         ev_view_find_previous (EV_VIEW (ev_window->priv->view));
5104 }
5105
5106 static void
5107 find_bar_next_cb (EggFindBar *find_bar,
5108                   EvWindow   *ev_window)
5109 {
5110         ev_view_find_next (EV_VIEW (ev_window->priv->view));
5111 }
5112
5113 static void
5114 find_bar_close_cb (EggFindBar *find_bar,
5115                    EvWindow   *ev_window)
5116 {
5117         ev_view_find_cancel (EV_VIEW (ev_window->priv->view));
5118         ev_window_clear_find_job (ev_window);
5119         update_chrome_flag (ev_window, EV_CHROME_FINDBAR, FALSE);
5120         update_chrome_visibility (ev_window);
5121 }
5122
5123 static void
5124 find_bar_search_changed_cb (EggFindBar *find_bar,
5125                             GParamSpec *param,
5126                             EvWindow   *ev_window)
5127 {
5128         gboolean case_sensitive;
5129         const char *search_string;
5130
5131         if (!ev_window->priv->document || !EV_IS_DOCUMENT_FIND (ev_window->priv->document))
5132                 return;
5133         
5134         /* Either the string or case sensitivity could have changed. */
5135         case_sensitive = egg_find_bar_get_case_sensitive (find_bar);
5136         search_string = egg_find_bar_get_search_string (find_bar);
5137
5138         ev_view_find_search_changed (EV_VIEW (ev_window->priv->view));
5139
5140         ev_window_clear_find_job (ev_window);
5141
5142         if (search_string && search_string[0]) {
5143                 ev_window->priv->find_job = ev_job_find_new (ev_window->priv->document,
5144                                                              ev_document_model_get_page (ev_window->priv->model),
5145                                                              ev_document_get_n_pages (ev_window->priv->document),
5146                                                              search_string,
5147                                                              case_sensitive);
5148                 g_signal_connect (ev_window->priv->find_job, "finished",
5149                                   G_CALLBACK (ev_window_find_job_finished_cb),
5150                                   ev_window);
5151                 g_signal_connect (ev_window->priv->find_job, "updated",
5152                                   G_CALLBACK (ev_window_find_job_updated_cb),
5153                                   ev_window);
5154                 ev_job_scheduler_push_job (ev_window->priv->find_job, EV_JOB_PRIORITY_NONE);
5155         } else {
5156                 ev_window_update_actions (ev_window);
5157                 egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar),
5158                                               NULL);
5159                 gtk_widget_queue_draw (GTK_WIDGET (ev_window->priv->view));
5160         }
5161 }
5162
5163 static void
5164 find_bar_visibility_changed_cb (EggFindBar *find_bar,
5165                                 GParamSpec *param,
5166                                 EvWindow   *ev_window)
5167 {
5168         gboolean visible;
5169
5170         visible = gtk_widget_get_visible (GTK_WIDGET (find_bar));
5171
5172         if (ev_window->priv->document &&
5173             EV_IS_DOCUMENT_FIND (ev_window->priv->document)) {
5174                 ev_view_find_set_highlight_search (EV_VIEW (ev_window->priv->view), visible);
5175                 ev_view_find_search_changed (EV_VIEW (ev_window->priv->view));
5176                 ev_window_update_actions (ev_window);
5177
5178                 if (visible)
5179                         find_bar_search_changed_cb (find_bar, NULL, ev_window);
5180                 else
5181                         egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar), NULL);
5182         }
5183 }
5184
5185 static void
5186 find_bar_scroll (EggFindBar   *find_bar,
5187                  GtkScrollType scroll,
5188                  EvWindow     *ev_window)
5189 {
5190         ev_view_scroll (EV_VIEW (ev_window->priv->view), scroll, FALSE);
5191 }
5192
5193 static void
5194 zoom_control_changed_cb (EphyZoomAction *action,
5195                          float           zoom,
5196                          EvWindow       *ev_window)
5197 {
5198         EvSizingMode mode;
5199
5200         if (zoom == EPHY_ZOOM_BEST_FIT) {
5201                 mode = EV_SIZING_BEST_FIT;
5202         } else if (zoom == EPHY_ZOOM_FIT_WIDTH) {
5203                 mode = EV_SIZING_FIT_WIDTH;
5204         } else {
5205                 mode = EV_SIZING_FREE;
5206         }
5207
5208         ev_document_model_set_sizing_mode (ev_window->priv->model, mode);
5209
5210         if (mode == EV_SIZING_FREE) {
5211                 ev_document_model_set_scale (ev_window->priv->model,
5212                                              zoom * get_screen_dpi (ev_window) / 72.0);
5213         }
5214 }
5215
5216 static void
5217 ev_window_drag_data_received (GtkWidget        *widget,
5218                               GdkDragContext   *context,
5219                               gint              x,
5220                               gint              y,
5221                               GtkSelectionData *selection_data,
5222                               guint             info,
5223                               guint             time)
5224
5225 {
5226         EvWindow  *window = EV_WINDOW (widget);
5227         gchar    **uris;
5228         gint       i = 0;
5229         GSList    *uri_list = NULL;
5230         GtkWidget *source;
5231
5232         source = gtk_drag_get_source_widget (context);
5233         if (source && widget == gtk_widget_get_toplevel (source)) {
5234                 gtk_drag_finish (context, FALSE, FALSE, time);
5235                 return;
5236         }
5237
5238         uris = gtk_selection_data_get_uris (selection_data);
5239         if (!uris) {
5240                 gtk_drag_finish (context, FALSE, FALSE, time);
5241                 return;
5242         }
5243
5244         for (i = 0; uris[i]; i++) {
5245                 uri_list = g_slist_prepend (uri_list, (gpointer) uris[i]);
5246         }
5247
5248         ev_application_open_uri_list (EV_APP, uri_list,
5249                                       gtk_window_get_screen (GTK_WINDOW (window)),
5250                                       0);
5251         gtk_drag_finish (context, TRUE, FALSE, time);
5252
5253         g_strfreev (uris);
5254         g_slist_free (uri_list);
5255 }
5256
5257 static void
5258 ev_window_finalize (GObject *object)
5259 {
5260         G_OBJECT_CLASS (ev_window_parent_class)->finalize (object);
5261
5262         if (ev_window_n_copies == 0) {
5263                 ev_application_shutdown (EV_APP);
5264         } else {
5265                 ev_window_n_copies--;
5266         }
5267 }
5268
5269 static void
5270 ev_window_dispose (GObject *object)
5271 {
5272         EvWindow *window = EV_WINDOW (object);
5273         EvWindowPrivate *priv = window->priv;
5274         GObject *mpkeys = ev_application_get_media_keys (EV_APP);
5275
5276         if (mpkeys) {
5277                 g_signal_handlers_disconnect_by_func (mpkeys,
5278                                                       ev_window_media_player_key_pressed,
5279                                                       window);
5280         }
5281
5282 #ifdef ENABLE_DBUS
5283         if (priv->dbus_object_id > 0) {
5284                 ev_window_emit_closed (window);
5285                 g_dbus_connection_unregister_object (ev_application_get_dbus_connection (EV_APP),
5286                                                      priv->dbus_object_id);
5287                 priv->dbus_object_id = 0;
5288         }
5289
5290         if (priv->dbus_object_path) {
5291                 g_free (priv->dbus_object_path);
5292                 priv->dbus_object_path = NULL;
5293         }
5294 #endif /* ENABLE_DBUS */
5295
5296         if (priv->bookmarks) {
5297                 g_object_unref (priv->bookmarks);
5298                 priv->bookmarks = NULL;
5299         }
5300
5301         if (priv->metadata) {
5302                 g_object_unref (priv->metadata);
5303                 priv->metadata = NULL;
5304         }
5305
5306         if (priv->setup_document_idle > 0) {
5307                 g_source_remove (priv->setup_document_idle);
5308                 priv->setup_document_idle = 0;
5309         }
5310
5311         if (priv->monitor) {
5312                 g_object_unref (priv->monitor);
5313                 priv->monitor = NULL;
5314         }
5315         
5316         if (priv->title) {
5317                 ev_window_title_free (priv->title);
5318                 priv->title = NULL;
5319         }
5320
5321         if (priv->ui_manager) {
5322                 g_object_unref (priv->ui_manager);
5323                 priv->ui_manager = NULL;
5324         }
5325
5326         if (priv->action_group) {
5327                 g_object_unref (priv->action_group);
5328                 priv->action_group = NULL;
5329         }
5330
5331         if (priv->view_popup_action_group) {
5332                 g_object_unref (priv->view_popup_action_group);
5333                 priv->view_popup_action_group = NULL;
5334         }
5335
5336         if (priv->attachment_popup_action_group) {
5337                 g_object_unref (priv->attachment_popup_action_group);
5338                 priv->attachment_popup_action_group = NULL;
5339         }
5340
5341         if (priv->recent_action_group) {
5342                 g_object_unref (priv->recent_action_group);
5343                 priv->recent_action_group = NULL;
5344         }
5345
5346         if (priv->bookmarks_action_group) {
5347                 g_object_unref (priv->bookmarks_action_group);
5348                 priv->bookmarks_action_group = NULL;
5349         }
5350
5351         if (priv->recent_manager) {
5352                 g_signal_handlers_disconnect_by_func (priv->recent_manager,
5353                                                       ev_window_setup_recent,
5354                                                       window);
5355                 priv->recent_manager = NULL;
5356         }
5357
5358         if (priv->settings) {
5359                 g_object_unref (priv->settings);
5360                 priv->settings = NULL;
5361         }
5362
5363         if (priv->default_settings) {
5364                 g_settings_apply (priv->default_settings);
5365                 g_object_unref (priv->default_settings);
5366                 priv->default_settings = NULL;
5367         }
5368
5369         if (priv->lockdown_settings) {
5370                 g_object_unref (priv->lockdown_settings);
5371                 priv->lockdown_settings = NULL;
5372         }
5373
5374         priv->recent_ui_id = 0;
5375
5376         if (priv->model) {
5377                 g_signal_handlers_disconnect_by_func (priv->model,
5378                                                       ev_window_page_changed_cb,
5379                                                       window);
5380                 g_object_unref (priv->model);
5381                 priv->model = NULL;
5382         }
5383
5384         if (priv->document) {
5385                 g_object_unref (priv->document);
5386                 priv->document = NULL;
5387         }
5388         
5389         if (priv->view) {
5390                 g_object_unref (priv->view);
5391                 priv->view = NULL;
5392         }
5393
5394         if (priv->password_view) {
5395                 g_object_unref (priv->password_view);
5396                 priv->password_view = NULL;
5397         }
5398
5399         if (priv->load_job) {
5400                 ev_window_clear_load_job (window);
5401         }
5402
5403         if (priv->reload_job) {
5404                 ev_window_clear_reload_job (window);
5405         }
5406
5407         if (priv->save_job) {
5408                 ev_window_clear_save_job (window);
5409         }
5410
5411         if (priv->thumbnail_job) {
5412                 ev_window_clear_thumbnail_job (window);
5413         }
5414
5415         if (priv->find_job) {
5416                 ev_window_clear_find_job (window);
5417         }
5418         
5419         if (priv->local_uri) {
5420                 ev_window_clear_local_uri (window);
5421                 priv->local_uri = NULL;
5422         }
5423
5424         ev_window_clear_progress_idle (window);
5425         if (priv->progress_cancellable) {
5426                 g_object_unref (priv->progress_cancellable);
5427                 priv->progress_cancellable = NULL;
5428         }
5429         
5430         ev_window_close_dialogs (window);
5431
5432         if (priv->link) {
5433                 g_object_unref (priv->link);
5434                 priv->link = NULL;
5435         }
5436
5437         if (priv->image) {
5438                 g_object_unref (priv->image);
5439                 priv->image = NULL;
5440         }
5441
5442         if (priv->annot) {
5443                 g_object_unref (priv->annot);
5444                 priv->annot = NULL;
5445         }
5446
5447         if (priv->attach_list) {
5448                 g_list_foreach (priv->attach_list,
5449                                 (GFunc) g_object_unref,
5450                                 NULL);
5451                 g_list_free (priv->attach_list);
5452                 priv->attach_list = NULL;
5453         }
5454
5455         if (priv->find_bar) {
5456                 g_signal_handlers_disconnect_by_func
5457                         (window->priv->find_bar,
5458                          G_CALLBACK (find_bar_close_cb),
5459                          window);
5460                 priv->find_bar = NULL;
5461         }
5462
5463         if (priv->uri) {
5464                 g_free (priv->uri);
5465                 priv->uri = NULL;
5466         }
5467
5468         if (priv->search_string) {
5469                 g_free (priv->search_string);
5470                 priv->search_string = NULL;
5471         }
5472         
5473         if (priv->dest) {
5474                 g_object_unref (priv->dest);
5475                 priv->dest = NULL;
5476         }
5477
5478         if (priv->history) {
5479                 g_object_unref (priv->history);
5480                 priv->history = NULL;
5481         }
5482
5483         if (priv->print_queue) {
5484                 g_queue_free (priv->print_queue);
5485                 priv->print_queue = NULL;
5486         }
5487
5488         G_OBJECT_CLASS (ev_window_parent_class)->dispose (object);
5489 }
5490
5491 static void
5492 menubar_deactivate_cb (GtkWidget *menubar,
5493                        EvWindow  *window)
5494 {
5495         g_signal_handlers_disconnect_by_func (menubar,
5496                                               G_CALLBACK (menubar_deactivate_cb),
5497                                               window);
5498
5499         gtk_menu_shell_deselect (GTK_MENU_SHELL (menubar));
5500
5501         update_chrome_visibility (window);
5502 }
5503
5504 static gboolean
5505 ev_window_key_press_event (GtkWidget   *widget,
5506                            GdkEventKey *event)
5507 {
5508         EvWindow        *ev_window = EV_WINDOW (widget);
5509         EvWindowPrivate *priv = ev_window->priv;
5510         gboolean         handled = FALSE;
5511
5512         /* Propagate the event to the view first
5513          * It's needed to be able to type in
5514          * annot popups windows
5515          */
5516         if (priv->view) {
5517                 g_object_ref (priv->view);
5518                 if (gtk_widget_is_sensitive (priv->view))
5519                         handled = gtk_widget_event (priv->view, (GdkEvent*) event);
5520                 g_object_unref (priv->view);
5521         }
5522
5523         if (!handled && !EV_WINDOW_IS_PRESENTATION (ev_window)) {
5524                 guint modifier = event->state & gtk_accelerator_get_default_mod_mask ();
5525
5526                 if (priv->menubar_accel_keyval != 0 &&
5527                     event->keyval == priv->menubar_accel_keyval &&
5528                     modifier == priv->menubar_accel_modifier) {
5529                         if (!gtk_widget_get_visible (priv->menubar)) {
5530                                 g_signal_connect (priv->menubar, "deactivate",
5531                                                   G_CALLBACK (menubar_deactivate_cb),
5532                                                   ev_window);
5533
5534                                 gtk_widget_show (priv->menubar);
5535                                 gtk_menu_shell_select_first (GTK_MENU_SHELL (priv->menubar),
5536                                                              FALSE);
5537
5538                                 handled = TRUE;
5539                         }
5540                 }
5541         }
5542
5543         if (!handled)
5544                 handled = GTK_WIDGET_CLASS (ev_window_parent_class)->key_press_event (widget, event);
5545
5546         return handled;
5547 }
5548
5549 static gboolean
5550 ev_window_delete_event (GtkWidget   *widget,
5551                         GdkEventAny *event)
5552 {
5553         return !ev_window_close (EV_WINDOW (widget));
5554 }
5555
5556 static void
5557 ev_window_class_init (EvWindowClass *ev_window_class)
5558 {
5559         GObjectClass *g_object_class = G_OBJECT_CLASS (ev_window_class);
5560         GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (ev_window_class);
5561
5562         g_object_class->dispose = ev_window_dispose;
5563         g_object_class->finalize = ev_window_finalize;
5564
5565         widget_class->delete_event = ev_window_delete_event;
5566         widget_class->key_press_event = ev_window_key_press_event;
5567         widget_class->screen_changed = ev_window_screen_changed;
5568         widget_class->window_state_event = ev_window_state_event;
5569         widget_class->drag_data_received = ev_window_drag_data_received;
5570
5571         g_type_class_add_private (g_object_class, sizeof (EvWindowPrivate));
5572 }
5573
5574 /* Normal items */
5575 static const GtkActionEntry entries[] = {
5576         { "File", NULL, N_("_File") },
5577         { "Edit", NULL, N_("_Edit") },
5578         { "View", NULL, N_("_View") },
5579         { "Go", NULL, N_("_Go") },
5580         { "Bookmarks", NULL, N_("_Bookmarks") },
5581         { "Help", NULL, N_("_Help") },
5582
5583         /* File menu */
5584         { "FileOpen", GTK_STOCK_OPEN, N_("_Open…"), "<control>O",
5585           N_("Open an existing document"),
5586           G_CALLBACK (ev_window_cmd_file_open) },
5587         { "FileOpenCopy", NULL, N_("Op_en a Copy"), "<control>N",
5588           N_("Open a copy of the current document in a new window"),
5589           G_CALLBACK (ev_window_cmd_file_open_copy) },
5590         { "FileSaveAs", GTK_STOCK_SAVE_AS, N_("_Save a Copy…"), "<control>S",
5591           N_("Save a copy of the current document"),
5592           G_CALLBACK (ev_window_cmd_save_as) },
5593         { "FileOpenContainingFolder", GTK_STOCK_DIRECTORY, N_("Open Containing _Folder"), NULL,
5594           N_("Show the folder which contains this file in the file manager"),
5595           G_CALLBACK (ev_window_cmd_open_containing_folder) },
5596         { "FilePrint", GTK_STOCK_PRINT, N_("_Print…"), "<control>P",
5597           N_("Print this document"),
5598           G_CALLBACK (ev_window_cmd_file_print) },
5599         { "FileProperties", GTK_STOCK_PROPERTIES, N_("P_roperties"), "<alt>Return", NULL,
5600           G_CALLBACK (ev_window_cmd_file_properties) },                       
5601         { "FileCloseWindow", GTK_STOCK_CLOSE, NULL, "<control>W", NULL,
5602           G_CALLBACK (ev_window_cmd_file_close_window) },
5603
5604         /* Edit menu */
5605         { "EditCopy", GTK_STOCK_COPY, NULL, "<control>C", NULL,
5606           G_CALLBACK (ev_window_cmd_edit_copy) },
5607         { "EditSelectAll", GTK_STOCK_SELECT_ALL, N_("Select _All"), "<control>A", NULL,
5608           G_CALLBACK (ev_window_cmd_edit_select_all) },
5609         { "EditFind", GTK_STOCK_FIND, N_("_Find…"), "<control>F",
5610           N_("Find a word or phrase in the document"),
5611           G_CALLBACK (ev_window_cmd_edit_find) },
5612         { "EditFindNext", NULL, N_("Find Ne_xt"), "<control>G", NULL,
5613           G_CALLBACK (ev_window_cmd_edit_find_next) },
5614         { "EditFindPrevious", NULL, N_("Find Pre_vious"), "<shift><control>G", NULL,
5615           G_CALLBACK (ev_window_cmd_edit_find_previous) },
5616         { "EditToolbar", NULL, N_("T_oolbar"), NULL, NULL,
5617           G_CALLBACK (ev_window_cmd_edit_toolbar) },
5618         { "EditRotateLeft", EV_STOCK_ROTATE_LEFT, N_("Rotate _Left"), "<control>Left", NULL,
5619           G_CALLBACK (ev_window_cmd_edit_rotate_left) },
5620         { "EditRotateRight", EV_STOCK_ROTATE_RIGHT, N_("Rotate _Right"), "<control>Right", NULL,
5621           G_CALLBACK (ev_window_cmd_edit_rotate_right) },
5622         { "EditSaveSettings", NULL, N_("Save Current Settings as _Default"), "<control>T", NULL,
5623           G_CALLBACK (ev_window_cmd_edit_save_settings) },
5624
5625
5626         /* View menu */
5627         { "ViewZoomIn", GTK_STOCK_ZOOM_IN, NULL, "<control>plus",
5628           N_("Enlarge the document"),
5629           G_CALLBACK (ev_window_cmd_view_zoom_in) },
5630         { "ViewZoomOut", GTK_STOCK_ZOOM_OUT, NULL, "<control>minus",
5631           N_("Shrink the document"),
5632           G_CALLBACK (ev_window_cmd_view_zoom_out) },
5633         { "ViewReload", GTK_STOCK_REFRESH, N_("_Reload"), "<control>R",
5634           N_("Reload the document"),
5635           G_CALLBACK (ev_window_cmd_view_reload) },
5636
5637         { "ViewAutoscroll", GTK_STOCK_MEDIA_PLAY, N_("Auto_scroll"), NULL, NULL,
5638           G_CALLBACK (ev_window_cmd_view_autoscroll) },
5639
5640         /* Go menu */
5641         { "GoPreviousPage", GTK_STOCK_GO_UP, N_("_Previous Page"), "<control>Page_Up",
5642           N_("Go to the previous page"),
5643           G_CALLBACK (ev_window_cmd_go_previous_page) },
5644         { "GoNextPage", GTK_STOCK_GO_DOWN, N_("_Next Page"), "<control>Page_Down",
5645           N_("Go to the next page"),
5646           G_CALLBACK (ev_window_cmd_go_next_page) },
5647         { "GoFirstPage", GTK_STOCK_GOTO_TOP, N_("_First Page"), "<control>Home",
5648           N_("Go to the first page"),
5649           G_CALLBACK (ev_window_cmd_go_first_page) },
5650         { "GoLastPage", GTK_STOCK_GOTO_BOTTOM, N_("_Last Page"), "<control>End",
5651           N_("Go to the last page"),
5652           G_CALLBACK (ev_window_cmd_go_last_page) },
5653
5654         /* Bookmarks menu */
5655         { "BookmarksAdd", GTK_STOCK_ADD, N_("_Add Bookmark"), "<control>D",
5656           N_("Add a bookmark for the current page"),
5657           G_CALLBACK (ev_window_cmd_bookmarks_add) },
5658
5659         /* Help menu */
5660         { "HelpContents", GTK_STOCK_HELP, N_("_Contents"), "F1", NULL,
5661           G_CALLBACK (ev_window_cmd_help_contents) },
5662
5663         { "HelpAbout", GTK_STOCK_ABOUT, N_("_About"), NULL, NULL,
5664           G_CALLBACK (ev_window_cmd_help_about) },
5665
5666         /* Toolbar-only */
5667         { "LeaveFullscreen", GTK_STOCK_LEAVE_FULLSCREEN, N_("Leave Fullscreen"), NULL,
5668           N_("Leave fullscreen mode"),
5669           G_CALLBACK (ev_window_cmd_leave_fullscreen) },
5670         { "StartPresentation", EV_STOCK_RUN_PRESENTATION, N_("Start Presentation"), NULL,
5671           N_("Start a presentation"),
5672           G_CALLBACK (ev_window_cmd_start_presentation) },
5673
5674         /* Accellerators */
5675         { "Escape", NULL, "", "Escape", "",
5676           G_CALLBACK (ev_window_cmd_escape) },
5677         { "Slash", GTK_STOCK_FIND, NULL, "slash", NULL,
5678           G_CALLBACK (ev_window_cmd_edit_find) },
5679         { "F3", NULL, "", "F3", NULL,
5680           G_CALLBACK (ev_window_cmd_edit_find_next) },
5681         { "PageDown", NULL, "", "Page_Down", NULL,
5682           G_CALLBACK (ev_window_cmd_scroll_forward) },
5683         { "PageUp", NULL, "", "Page_Up", NULL,
5684           G_CALLBACK (ev_window_cmd_scroll_backward) },
5685         { "Space", NULL, "", "space", NULL,
5686           G_CALLBACK (ev_window_cmd_scroll_forward) },
5687         { "ShiftSpace", NULL, "", "<shift>space", NULL,
5688           G_CALLBACK (ev_window_cmd_scroll_backward) },
5689         { "BackSpace", NULL, "", "BackSpace", NULL,
5690           G_CALLBACK (ev_window_cmd_scroll_backward) },
5691         { "ShiftBackSpace", NULL, "", "<shift>BackSpace", NULL,
5692           G_CALLBACK (ev_window_cmd_scroll_forward) },
5693         { "Return", NULL, "", "Return", NULL,
5694           G_CALLBACK (ev_window_cmd_scroll_forward) },
5695         { "ShiftReturn", NULL, "", "<shift>Return", NULL,
5696           G_CALLBACK (ev_window_cmd_scroll_backward) },
5697         { "p", GTK_STOCK_GO_UP, "", "p", NULL,
5698           G_CALLBACK (ev_window_cmd_go_previous_page) },
5699         { "n", GTK_STOCK_GO_DOWN, "", "n", NULL,
5700           G_CALLBACK (ev_window_cmd_go_next_page) },
5701         { "Plus", GTK_STOCK_ZOOM_IN, NULL, "plus", NULL,
5702           G_CALLBACK (ev_window_cmd_view_zoom_in) },
5703         { "CtrlEqual", GTK_STOCK_ZOOM_IN, NULL, "<control>equal", NULL,
5704           G_CALLBACK (ev_window_cmd_view_zoom_in) },
5705         { "Equal", GTK_STOCK_ZOOM_IN, NULL, "equal", NULL,
5706           G_CALLBACK (ev_window_cmd_view_zoom_in) },
5707         { "Minus", GTK_STOCK_ZOOM_OUT, NULL, "minus", NULL,
5708           G_CALLBACK (ev_window_cmd_view_zoom_out) },
5709         { "FocusPageSelector", NULL, "", "<control>l", NULL,
5710           G_CALLBACK (ev_window_cmd_focus_page_selector) },
5711         { "GoBackwardFast", NULL, "", "<shift>Page_Up", NULL,
5712           G_CALLBACK (ev_window_cmd_go_backward) },
5713         { "GoForwardFast", NULL, "", "<shift>Page_Down", NULL,
5714           G_CALLBACK (ev_window_cmd_go_forward) },
5715         { "KpPlus", GTK_STOCK_ZOOM_IN, NULL, "KP_Add", NULL,
5716           G_CALLBACK (ev_window_cmd_view_zoom_in) },
5717         { "KpMinus", GTK_STOCK_ZOOM_OUT, NULL, "KP_Subtract", NULL,
5718           G_CALLBACK (ev_window_cmd_view_zoom_out) },
5719         { "CtrlKpPlus", GTK_STOCK_ZOOM_IN, NULL, "<control>KP_Add", NULL,
5720           G_CALLBACK (ev_window_cmd_view_zoom_in) },
5721         { "CtrlKpMinus", GTK_STOCK_ZOOM_OUT, NULL, "<control>KP_Subtract", NULL,
5722           G_CALLBACK (ev_window_cmd_view_zoom_out) },
5723         { "CtrlInsert", GTK_STOCK_COPY, NULL, "<control>Insert", NULL,
5724           G_CALLBACK (ev_window_cmd_edit_copy) },
5725 };
5726
5727 /* Toggle items */
5728 static const GtkToggleActionEntry toggle_entries[] = {
5729         /* View Menu */
5730         { "ViewToolbar", NULL, N_("_Toolbar"), NULL,
5731           N_("Show or hide the toolbar"),
5732           G_CALLBACK (ev_window_view_toolbar_cb), TRUE },
5733         { "ViewSidebar", GTK_STOCK_INDEX, N_("Side _Pane"), "F9",
5734           N_("Show or hide the side pane"),
5735           G_CALLBACK (ev_window_view_sidebar_cb), TRUE },
5736         { "ViewContinuous", EV_STOCK_VIEW_CONTINUOUS, N_("_Continuous"), NULL,
5737           N_("Show the entire document"),
5738           G_CALLBACK (ev_window_cmd_continuous), TRUE },
5739         { "ViewDual", EV_STOCK_VIEW_DUAL, N_("_Dual"), NULL,
5740           N_("Show two pages at once"),
5741           G_CALLBACK (ev_window_cmd_dual), FALSE },
5742         { "ViewFullscreen", GTK_STOCK_FULLSCREEN, N_("_Fullscreen"), "F11",
5743           N_("Expand the window to fill the screen"),
5744           G_CALLBACK (ev_window_cmd_view_fullscreen) },
5745         { "ViewPresentation", EV_STOCK_RUN_PRESENTATION, N_("Pre_sentation"), "F5",
5746           N_("Run document as a presentation"),
5747           G_CALLBACK (ev_window_cmd_view_presentation) },
5748         { "ViewBestFit", EV_STOCK_ZOOM_PAGE, N_("_Best Fit"), NULL,
5749           N_("Make the current document fill the window"),
5750           G_CALLBACK (ev_window_cmd_view_best_fit) },
5751         { "ViewPageWidth", EV_STOCK_ZOOM_WIDTH, N_("Fit Page _Width"), NULL,
5752           N_("Make the current document fill the window width"),
5753           G_CALLBACK (ev_window_cmd_view_page_width) },
5754         { "ViewInvertedColors", EV_STOCK_INVERTED_COLORS, N_("_Inverted Colors"), "<control>I",
5755           N_("Show page contents with the colors inverted"),
5756           G_CALLBACK (ev_window_cmd_view_inverted_colors) },
5757
5758 };
5759
5760 /* Popups specific items */
5761 static const GtkActionEntry view_popup_entries [] = {
5762         /* Links */
5763         { "OpenLink", GTK_STOCK_OPEN, N_("_Open Link"), NULL,
5764           NULL, G_CALLBACK (ev_view_popup_cmd_open_link) },
5765         { "GoLink", GTK_STOCK_GO_FORWARD, N_("_Go To"), NULL,
5766           NULL, G_CALLBACK (ev_view_popup_cmd_open_link) },
5767         { "OpenLinkNewWindow", NULL, N_("Open in New _Window"), NULL,
5768           NULL, G_CALLBACK (ev_view_popup_cmd_open_link_new_window) },
5769         { "CopyLinkAddress", NULL, N_("_Copy Link Address"), NULL,
5770           NULL, G_CALLBACK (ev_view_popup_cmd_copy_link_address) },
5771         { "SaveImageAs", NULL, N_("_Save Image As…"), NULL,
5772           NULL, G_CALLBACK (ev_view_popup_cmd_save_image_as) },
5773         { "CopyImage", NULL, N_("Copy _Image"), NULL,
5774           NULL, G_CALLBACK (ev_view_popup_cmd_copy_image) },
5775         { "AnnotProperties", NULL, N_("Annotation Properties…"), NULL,
5776           NULL, G_CALLBACK (ev_view_popup_cmd_annot_properties) }
5777 };
5778
5779 static const GtkActionEntry attachment_popup_entries [] = {
5780         { "OpenAttachment", GTK_STOCK_OPEN, N_("_Open Attachment"), NULL,
5781           NULL, G_CALLBACK (ev_attachment_popup_cmd_open_attachment) },
5782         { "SaveAttachmentAs", GTK_STOCK_SAVE_AS, N_("_Save Attachment As…"), NULL,
5783           NULL, G_CALLBACK (ev_attachment_popup_cmd_save_attachment_as) },
5784 };
5785
5786 static void
5787 sidebar_links_link_activated_cb (EvSidebarLinks *sidebar_links, EvLink *link, EvWindow *window)
5788 {
5789         ev_view_handle_link (EV_VIEW (window->priv->view), link);
5790 }
5791
5792 static void
5793 activate_link_cb (EvPageAction *page_action, EvLink *link, EvWindow *window)
5794 {
5795         ev_view_handle_link (EV_VIEW (window->priv->view), link);
5796         gtk_widget_grab_focus (window->priv->view);
5797 }
5798
5799 static void
5800 navigation_action_activate_link_cb (EvNavigationAction *action, EvLink *link, EvWindow *window)
5801 {
5802         
5803         ev_view_handle_link (EV_VIEW (window->priv->view), link);
5804         gtk_widget_grab_focus (window->priv->view);
5805 }
5806
5807 static void
5808 sidebar_layers_visibility_changed (EvSidebarLayers *layers,
5809                                    EvWindow        *window)
5810 {
5811         ev_view_reload (EV_VIEW (window->priv->view));
5812 }
5813
5814 static void
5815 sidebar_annots_annot_activated_cb (EvSidebarAnnotations *sidebar_annots,
5816                                    EvMapping            *annot_mapping,
5817                                    EvWindow             *window)
5818 {
5819         ev_view_focus_annotation (EV_VIEW (window->priv->view), annot_mapping);
5820 }
5821
5822 static void
5823 sidebar_annots_begin_annot_add (EvSidebarAnnotations *sidebar_annots,
5824                                 EvAnnotationType      annot_type,
5825                                 EvWindow             *window)
5826 {
5827         ev_view_begin_add_annotation (EV_VIEW (window->priv->view), annot_type);
5828 }
5829
5830 static void
5831 view_annot_added (EvView       *view,
5832                   EvAnnotation *annot,
5833                   EvWindow     *window)
5834 {
5835         ev_sidebar_annotations_annot_added (EV_SIDEBAR_ANNOTATIONS (window->priv->sidebar_annots),
5836                                             annot);
5837 }
5838
5839 static void
5840 sidebar_annots_annot_add_cancelled (EvSidebarAnnotations *sidebar_annots,
5841                                     EvWindow             *window)
5842 {
5843         ev_view_cancel_add_annotation (EV_VIEW (window->priv->view));
5844 }
5845
5846 static void
5847 register_custom_actions (EvWindow *window, GtkActionGroup *group)
5848 {
5849         GtkAction *action;
5850
5851         action = g_object_new (EV_TYPE_PAGE_ACTION,
5852                                "name", PAGE_SELECTOR_ACTION,
5853                                "label", _("Page"),
5854                                "tooltip", _("Select Page"),
5855                                "icon_name", "text-x-generic",
5856                                "visible_overflown", FALSE,
5857                                NULL);
5858         ev_page_action_set_model (EV_PAGE_ACTION (action),
5859                                   window->priv->model);
5860         g_signal_connect (action, "activate_link",
5861                           G_CALLBACK (activate_link_cb), window);
5862         gtk_action_group_add_action (group, action);
5863         g_object_unref (action);
5864
5865         action = g_object_new (EPHY_TYPE_ZOOM_ACTION,
5866                                "name", ZOOM_CONTROL_ACTION,
5867                                "label", _("Zoom"),
5868                                "stock_id", EV_STOCK_ZOOM,
5869                                "tooltip", _("Adjust the zoom level"),
5870                                "zoom", 1.0,
5871                                NULL);
5872         g_signal_connect (action, "zoom_to_level",
5873                           G_CALLBACK (zoom_control_changed_cb), window);
5874         gtk_action_group_add_action (group, action);
5875         g_object_unref (action);
5876
5877         action = g_object_new (EV_TYPE_NAVIGATION_ACTION,
5878                                "name", NAVIGATION_ACTION,
5879                                "label", _("Navigation"),
5880                                "is_important", TRUE,
5881                                "short_label", _("Back"),
5882                                "stock_id", GTK_STOCK_GO_DOWN,
5883                                /*translators: this is the history action*/
5884                                "tooltip", _("Move across visited pages"),
5885                                NULL);
5886         g_signal_connect (action, "activate_link",
5887                           G_CALLBACK (navigation_action_activate_link_cb), window);
5888         gtk_action_group_add_action (group, action);
5889         g_object_unref (action);
5890
5891         action = g_object_new (EV_TYPE_OPEN_RECENT_ACTION,
5892                                "name", "FileOpenRecent",
5893                                "label", _("_Open…"),
5894                                "tooltip", _("Open an existing document"),
5895                                "stock_id", GTK_STOCK_OPEN,
5896                                NULL);
5897         g_signal_connect (action, "activate",
5898                           G_CALLBACK (ev_window_cmd_file_open), window);
5899         g_signal_connect (action, "item_activated",
5900                           G_CALLBACK (ev_window_open_recent_action_item_activated),
5901                           window);
5902         gtk_action_group_add_action (group, action);
5903         g_object_unref (action);
5904 }
5905
5906 static void
5907 set_action_properties (GtkActionGroup *action_group)
5908 {
5909         GtkAction *action;
5910
5911         action = gtk_action_group_get_action (action_group, "FileOpenContainingFolder");
5912         /*translators: this is the label for toolbar button*/
5913         g_object_set (action, "short_label", _("Open Folder"), NULL);
5914
5915         action = gtk_action_group_get_action (action_group, "GoPreviousPage");
5916         g_object_set (action, "is-important", TRUE, NULL);
5917         /*translators: this is the label for toolbar button*/
5918         g_object_set (action, "short_label", _("Previous"), NULL);
5919
5920         action = gtk_action_group_get_action (action_group, "GoNextPage");
5921         g_object_set (action, "is-important", TRUE, NULL);
5922         /*translators: this is the label for toolbar button*/
5923         g_object_set (action, "short_label", _("Next"), NULL);
5924
5925         action = gtk_action_group_get_action (action_group, "ViewZoomIn");
5926         /*translators: this is the label for toolbar button*/
5927         g_object_set (action, "short_label", _("Zoom In"), NULL);
5928
5929         action = gtk_action_group_get_action (action_group, "ViewZoomOut");
5930         /*translators: this is the label for toolbar button*/
5931         g_object_set (action, "short_label", _("Zoom Out"), NULL);
5932
5933         action = gtk_action_group_get_action (action_group, "ViewBestFit");
5934         /*translators: this is the label for toolbar button*/
5935         g_object_set (action, "short_label", _("Best Fit"), NULL);
5936
5937         action = gtk_action_group_get_action (action_group, "ViewPageWidth");
5938         /*translators: this is the label for toolbar button*/
5939         g_object_set (action, "short_label", _("Fit Width"), NULL);
5940
5941         action = gtk_action_group_get_action (action_group, "LeaveFullscreen");
5942         g_object_set (action, "is-important", TRUE, NULL);
5943 }
5944
5945 static void
5946 sidebar_widget_model_set (EvSidebarLinks *ev_sidebar_links,
5947                           GParamSpec     *pspec,
5948                           EvWindow       *ev_window)
5949 {
5950         GtkTreeModel *model;
5951         GtkAction *action;
5952
5953         g_object_get (G_OBJECT (ev_sidebar_links),
5954                       "model", &model,
5955                       NULL);
5956
5957         action = gtk_action_group_get_action (ev_window->priv->action_group, PAGE_SELECTOR_ACTION);
5958         ev_page_action_set_links_model (EV_PAGE_ACTION (action), model);
5959         g_object_unref (model);
5960 }
5961
5962 static gboolean
5963 view_actions_focus_in_cb (GtkWidget *widget, GdkEventFocus *event, EvWindow *window)
5964 {
5965 #ifdef ENABLE_DBUS
5966         GObject *keys;
5967
5968         keys = ev_application_get_media_keys (EV_APP);
5969         ev_media_player_keys_focused (EV_MEDIA_PLAYER_KEYS (keys));
5970 #endif /* ENABLE_DBUS */
5971
5972         update_chrome_flag (window, EV_CHROME_RAISE_TOOLBAR, FALSE);
5973         ev_window_set_action_sensitive (window, "ViewToolbar", TRUE);
5974
5975         ev_window_set_view_accels_sensitivity (window, TRUE);
5976
5977         update_chrome_visibility (window);
5978
5979         return FALSE;
5980 }
5981
5982 static gboolean
5983 view_actions_focus_out_cb (GtkWidget *widget, GdkEventFocus *event, EvWindow *window)
5984 {
5985         ev_window_set_view_accels_sensitivity (window, FALSE);
5986
5987         return FALSE;
5988 }
5989
5990 static void
5991 sidebar_page_main_widget_update_cb (GObject *ev_sidebar_page,
5992                                     GParamSpec         *pspec,
5993                                     EvWindow           *ev_window)
5994 {
5995         GtkWidget *widget;
5996         
5997         g_object_get (ev_sidebar_page, "main_widget", &widget, NULL);
5998
5999         if (widget != NULL) {           
6000                 g_signal_connect_object (widget, "focus_in_event",
6001                                          G_CALLBACK (view_actions_focus_in_cb),
6002                                          ev_window, 0);
6003                 g_signal_connect_object (widget, "focus_out_event",
6004                                          G_CALLBACK (view_actions_focus_out_cb),
6005                                          ev_window, 0);
6006                 g_object_unref (widget);
6007         }
6008 }
6009
6010 static gboolean
6011 window_state_event_cb (EvWindow *window, GdkEventWindowState *event, gpointer dummy)
6012 {
6013         if (!(event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
6014                 gboolean maximized;
6015
6016                 maximized = event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED;
6017                 if (window->priv->metadata && !ev_window_is_empty (window))
6018                         ev_metadata_set_boolean (window->priv->metadata, "window_maximized", maximized);
6019         }
6020
6021         return FALSE;
6022 }
6023
6024 static gboolean
6025 window_configure_event_cb (EvWindow *window, GdkEventConfigure *event, gpointer dummy)
6026 {
6027         GdkWindowState state;
6028         gdouble document_width, document_height;
6029
6030         if (!window->priv->metadata)
6031                 return FALSE;
6032
6033         state = gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (window)));
6034
6035         if (!(state & GDK_WINDOW_STATE_FULLSCREEN)) {
6036                 if (window->priv->document) {
6037                         ev_document_get_max_page_size (window->priv->document,
6038                                                        &document_width, &document_height);
6039                         g_settings_set (window->priv->default_settings, "window-ratio", "(dd)",
6040                                         (double)event->width / document_width,
6041                                         (double)event->height / document_height);
6042
6043                         ev_metadata_set_int (window->priv->metadata, "window_x", event->x);
6044                         ev_metadata_set_int (window->priv->metadata, "window_y", event->y);
6045                         ev_metadata_set_int (window->priv->metadata, "window_width", event->width);
6046                         ev_metadata_set_int (window->priv->metadata, "window_height", event->height);
6047                 }
6048         }
6049
6050         return FALSE;
6051 }
6052
6053 static void
6054 launch_action (EvWindow *window, EvLinkAction *action)
6055 {
6056         const char *filename = ev_link_action_get_filename (action);
6057         GAppInfo *app_info;
6058         GFile *file;
6059         GList file_list = {NULL};
6060         GAppLaunchContext *context;
6061         GError *error = NULL;
6062
6063         if (filename == NULL)
6064                 return;
6065
6066         if (g_path_is_absolute (filename)) {
6067                 file = g_file_new_for_path (filename);
6068         } else {
6069                 GFile *base_file;
6070                 gchar *dir;
6071
6072                 dir = g_path_get_dirname (window->priv->uri);
6073                 base_file = g_file_new_for_uri (dir);
6074                 g_free (dir);
6075                 
6076                 file = g_file_resolve_relative_path (base_file, filename);
6077                 g_object_unref (base_file);
6078         }
6079
6080         app_info = g_file_query_default_handler (file, NULL, &error);
6081         if (!app_info) {
6082                 ev_window_error_message (window, error,
6083                                          "%s",
6084                                          _("Unable to launch external application."));
6085                 g_object_unref (file);
6086                 g_error_free (error);
6087
6088                 return;
6089         }
6090
6091         context = G_APP_LAUNCH_CONTEXT (gdk_app_launch_context_new ());
6092         gdk_app_launch_context_set_screen (GDK_APP_LAUNCH_CONTEXT (context),
6093                                            gtk_window_get_screen (GTK_WINDOW (window)));
6094         gdk_app_launch_context_set_timestamp (GDK_APP_LAUNCH_CONTEXT (context),
6095                                               gtk_get_current_event_time ());
6096         
6097         file_list.data = file;
6098         if (!g_app_info_launch (app_info, &file_list, context, &error)) {
6099                 ev_window_error_message (window, error,
6100                                          "%s",
6101                                          _("Unable to launch external application."));
6102                 g_error_free (error);
6103         }
6104         
6105         g_object_unref (app_info);
6106         g_object_unref (file);
6107         /* FIXMEchpe: unref launch context? */
6108
6109         /* According to the PDF spec filename can be an executable. I'm not sure
6110            allowing to launch executables is a good idea though. -- marco */
6111 }
6112
6113 static void
6114 launch_external_uri (EvWindow *window, EvLinkAction *action)
6115 {
6116         const gchar *uri = ev_link_action_get_uri (action);
6117         GError *error = NULL;
6118         gboolean ret;
6119         GAppLaunchContext *context;
6120
6121         context = G_APP_LAUNCH_CONTEXT (gdk_app_launch_context_new ());
6122         gdk_app_launch_context_set_screen (GDK_APP_LAUNCH_CONTEXT (context),
6123                                            gtk_window_get_screen (GTK_WINDOW (window)));
6124         gdk_app_launch_context_set_timestamp (GDK_APP_LAUNCH_CONTEXT (context),
6125                                               gtk_get_current_event_time ());
6126
6127         if (!g_strstr_len (uri, strlen (uri), "://") &&
6128             !g_str_has_prefix (uri, "mailto:")) {
6129                 gchar *new_uri;
6130
6131                 /* Not a valid uri, assume http if it starts with www */
6132                 if (g_str_has_prefix (uri, "www.")) {
6133                         new_uri = g_strdup_printf ("http://%s", uri);
6134                 } else {
6135                         GFile *file, *parent;
6136
6137                         file = g_file_new_for_uri (window->priv->uri);
6138                         parent = g_file_get_parent (file);
6139                         g_object_unref (file);
6140                         if (parent) {
6141                                 gchar *parent_uri = g_file_get_uri (parent);
6142
6143                                 new_uri = g_build_filename (parent_uri, uri, NULL);
6144                                 g_free (parent_uri);
6145                                 g_object_unref (parent);
6146                         } else {
6147                                 new_uri = g_strdup_printf ("file:///%s", uri);
6148                         }
6149                 }
6150                 ret = g_app_info_launch_default_for_uri (new_uri, context, &error);
6151                 g_free (new_uri);
6152         } else {
6153                 ret = g_app_info_launch_default_for_uri (uri, context, &error);
6154         }
6155
6156         if (ret == FALSE) {
6157                 ev_window_error_message (window, error,
6158                                          "%s", _("Unable to open external link"));
6159                 g_error_free (error);
6160         }
6161
6162         /* FIXMEchpe: unref launch context? */
6163 }
6164
6165 static void
6166 open_remote_link (EvWindow *window, EvLinkAction *action)
6167 {
6168         gchar *uri;
6169         gchar *dir;
6170
6171         dir = g_path_get_dirname (window->priv->uri);
6172         
6173         uri = g_build_filename (dir, ev_link_action_get_filename (action),
6174                                 NULL);
6175         g_free (dir);
6176
6177         ev_application_open_uri_at_dest (EV_APP, uri,
6178                                          gtk_window_get_screen (GTK_WINDOW (window)),
6179                                          ev_link_action_get_dest (action),
6180                                          0,
6181                                          NULL, 
6182                                          gtk_get_current_event_time ());
6183
6184         g_free (uri);
6185 }
6186
6187 static void
6188 do_action_named (EvWindow *window, EvLinkAction *action)
6189 {
6190         const gchar *name = ev_link_action_get_name (action);
6191
6192         if (g_ascii_strcasecmp (name, "FirstPage") == 0) {
6193                 ev_window_cmd_go_first_page (NULL, window);
6194         } else if (g_ascii_strcasecmp (name, "PrevPage") == 0) {
6195                 ev_window_cmd_go_previous_page (NULL, window);
6196         } else if (g_ascii_strcasecmp (name, "NextPage") == 0) {
6197                 ev_window_cmd_go_next_page (NULL, window);
6198         } else if (g_ascii_strcasecmp (name, "LastPage") == 0) {
6199                 ev_window_cmd_go_last_page (NULL, window);
6200         } else if (g_ascii_strcasecmp (name, "GoToPage") == 0) {
6201                 ev_window_cmd_focus_page_selector (NULL, window);
6202         } else if (g_ascii_strcasecmp (name, "Find") == 0) {
6203                 ev_window_cmd_edit_find (NULL, window);
6204         } else if (g_ascii_strcasecmp (name, "Close") == 0) {
6205                 ev_window_cmd_file_close_window (NULL, window);
6206         } else if (g_ascii_strcasecmp (name, "Print") == 0) {
6207                 ev_window_cmd_file_print (NULL, window);
6208         } else {
6209                 g_warning ("Unimplemented named action: %s, please post a "
6210                            "bug report in Evince bugzilla "
6211                            "(http://bugzilla.gnome.org) with a testcase.",
6212                            name);
6213         }
6214 }
6215
6216 static void
6217 view_external_link_cb (EvView *view, EvLinkAction *action, EvWindow *window)
6218 {
6219         switch (ev_link_action_get_action_type (action)) {
6220                 case EV_LINK_ACTION_TYPE_GOTO_DEST: {
6221                         EvLinkDest *dest;
6222                         
6223                         dest = ev_link_action_get_dest (action);
6224                         if (!dest)
6225                                 return;
6226
6227                         ev_window_open_copy_at_dest (window, dest);
6228                 }
6229                         break;
6230                 case EV_LINK_ACTION_TYPE_EXTERNAL_URI:
6231                         launch_external_uri (window, action);
6232                         break;
6233                 case EV_LINK_ACTION_TYPE_LAUNCH:
6234                         launch_action (window, action);
6235                         break;
6236                 case EV_LINK_ACTION_TYPE_GOTO_REMOTE:
6237                         open_remote_link (window, action);
6238                         break;
6239                 case EV_LINK_ACTION_TYPE_NAMED:
6240                         do_action_named (window, action);
6241                         break;
6242                 default:
6243                         g_assert_not_reached ();
6244         }
6245 }
6246
6247 static void
6248 ev_view_popup_cmd_open_link (GtkAction *action, EvWindow *window)
6249 {
6250         ev_view_handle_link (EV_VIEW (window->priv->view), window->priv->link);
6251 }
6252
6253 static void
6254 ev_view_popup_cmd_open_link_new_window (GtkAction *action, EvWindow *window)
6255 {
6256         EvLinkAction *ev_action = NULL;
6257         EvLinkDest   *dest;
6258
6259         ev_action = ev_link_get_action (window->priv->link);
6260         if (!ev_action)
6261                 return;
6262
6263         dest = ev_link_action_get_dest (ev_action);
6264         if (!dest)
6265                 return;
6266
6267         ev_window_open_copy_at_dest (window, dest);
6268 }
6269
6270 static void
6271 ev_view_popup_cmd_copy_link_address (GtkAction *action, EvWindow *window)
6272 {
6273         EvLinkAction *ev_action;
6274
6275         ev_action = ev_link_get_action (window->priv->link);
6276         if (!ev_action)
6277                 return;
6278
6279         ev_view_copy_link_address (EV_VIEW (window->priv->view),
6280                                    ev_action);
6281 }
6282
6283
6284 static void
6285 image_save_dialog_response_cb (GtkWidget *fc,
6286                                gint       response_id,
6287                                EvWindow  *ev_window)
6288 {
6289         GFile           *target_file;
6290         gboolean         is_native;
6291         GError          *error = NULL;
6292         GdkPixbuf       *pixbuf;
6293         gchar           *uri;
6294         gchar          **extensions;
6295         gchar           *filename;
6296         gchar           *file_format;
6297         GdkPixbufFormat *format;
6298         GtkFileFilter   *filter;
6299         
6300         if (response_id != GTK_RESPONSE_OK) {
6301                 gtk_widget_destroy (fc);
6302                 return;
6303         }
6304
6305         uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fc));
6306         filter = gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (fc));
6307         format = g_object_get_data (G_OBJECT (filter), "pixbuf-format");
6308         
6309         if (format == NULL) {
6310                 format = get_gdk_pixbuf_format_by_extension (uri);
6311         }
6312
6313         if (format == NULL && g_strrstr (uri, ".") == NULL) {
6314                 /* no extension found and no extension provided within uri */
6315                 format = get_gdk_pixbuf_format_by_extension (".png");
6316                 if (format == NULL) {
6317                         /* no .png support, try .jpeg */
6318                         format = get_gdk_pixbuf_format_by_extension (".jpeg");
6319                 }
6320         }
6321
6322         if (format == NULL) {
6323                 ev_window_error_message (ev_window, NULL, 
6324                                          "%s",
6325                                          _("Couldn't find appropriate format to save image"));
6326                 g_free (uri);
6327                 gtk_widget_destroy (fc);
6328
6329                 return;
6330         }
6331
6332         extensions = gdk_pixbuf_format_get_extensions (format);
6333         if (!g_str_has_suffix (uri, extensions[0])) {
6334                 gchar *uri_extension;
6335                 
6336                 uri_extension = g_strconcat (uri, ".", extensions[0], NULL);
6337                 target_file = g_file_new_for_uri (uri_extension);
6338                 g_free (uri_extension);
6339         } else {
6340                 target_file = g_file_new_for_uri (uri);
6341         }
6342         g_strfreev (extensions);
6343         g_free (uri);
6344         
6345         is_native = g_file_is_native (target_file);
6346         if (is_native) {
6347                 filename = g_file_get_path (target_file);
6348         } else {
6349                 /* Create a temporary local file to save to */
6350                 if (ev_mkstemp ("saveimage.XXXXXX", &filename, &error) == -1)
6351                         goto has_error;
6352         }
6353
6354         ev_document_doc_mutex_lock ();
6355         pixbuf = ev_document_images_get_image (EV_DOCUMENT_IMAGES (ev_window->priv->document),
6356                                                ev_window->priv->image);
6357         ev_document_doc_mutex_unlock ();
6358
6359         file_format = gdk_pixbuf_format_get_name (format);
6360         gdk_pixbuf_save (pixbuf, filename, file_format, &error, NULL);
6361         g_free (file_format);
6362         g_object_unref (pixbuf);
6363         
6364     has_error:
6365         if (error) {
6366                 ev_window_error_message (ev_window, error, 
6367                                          "%s", _("The image could not be saved."));
6368                 g_error_free (error);
6369                 g_free (filename);
6370                 g_object_unref (target_file);
6371                 gtk_widget_destroy (fc);
6372
6373                 return;
6374         }
6375
6376         if (!is_native) {
6377                 GFile *source_file;
6378                 
6379                 source_file = g_file_new_for_path (filename);
6380                 
6381                 ev_window_save_remote (ev_window, EV_SAVE_IMAGE,
6382                                        source_file, target_file);
6383                 g_object_unref (source_file);
6384         }
6385         
6386         g_free (filename);
6387         g_object_unref (target_file);
6388         gtk_widget_destroy (fc);
6389 }
6390
6391 static void
6392 ev_view_popup_cmd_save_image_as (GtkAction *action, EvWindow *window)
6393 {
6394         GtkWidget *fc;
6395
6396         if (!window->priv->image)
6397                 return;
6398
6399         fc = gtk_file_chooser_dialog_new (_("Save Image"),
6400                                           GTK_WINDOW (window),
6401                                           GTK_FILE_CHOOSER_ACTION_SAVE,
6402                                           GTK_STOCK_CANCEL,
6403                                           GTK_RESPONSE_CANCEL,
6404                                           GTK_STOCK_SAVE, GTK_RESPONSE_OK,
6405                                           NULL);
6406
6407         gtk_dialog_set_default_response (GTK_DIALOG (fc), GTK_RESPONSE_OK);
6408         gtk_dialog_set_alternative_button_order (GTK_DIALOG (fc),
6409                                                  GTK_RESPONSE_OK,
6410                                                  GTK_RESPONSE_CANCEL,
6411                                                  -1);
6412
6413         gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (fc), FALSE);
6414         gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (fc), TRUE);
6415         
6416         file_chooser_dialog_add_writable_pixbuf_formats (GTK_FILE_CHOOSER (fc));
6417         
6418         g_signal_connect (fc, "response",
6419                           G_CALLBACK (image_save_dialog_response_cb),
6420                           window);
6421
6422         gtk_widget_show (fc);
6423 }
6424
6425 static void
6426 ev_view_popup_cmd_copy_image (GtkAction *action, EvWindow *window)
6427 {
6428         GtkClipboard *clipboard;
6429         GdkPixbuf    *pixbuf;
6430
6431         if (!window->priv->image)
6432                 return;
6433         
6434         clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window),
6435                                               GDK_SELECTION_CLIPBOARD);
6436         ev_document_doc_mutex_lock ();
6437         pixbuf = ev_document_images_get_image (EV_DOCUMENT_IMAGES (window->priv->document),
6438                                                window->priv->image);
6439         ev_document_doc_mutex_unlock ();
6440         
6441         gtk_clipboard_set_image (clipboard, pixbuf);
6442         g_object_unref (pixbuf);
6443 }
6444
6445 static void
6446 ev_view_popup_cmd_annot_properties (GtkAction *action,
6447                                     EvWindow  *window)
6448 {
6449         const gchar                  *author;
6450         GdkColor                      color;
6451         gdouble                       opacity;
6452         gboolean                      popup_is_open;
6453         EvAnnotationPropertiesDialog *dialog;
6454         EvAnnotation                 *annot = window->priv->annot;
6455         EvAnnotationsSaveMask         mask = EV_ANNOTATIONS_SAVE_NONE;
6456
6457         if (!annot)
6458                 return;
6459
6460         dialog = EV_ANNOTATION_PROPERTIES_DIALOG (ev_annotation_properties_dialog_new_with_annotation (window->priv->annot));
6461         if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_APPLY) {
6462                 gtk_widget_destroy (GTK_WIDGET (dialog));
6463
6464                 return;
6465         }
6466
6467         /* Set annotations changes */
6468         author = ev_annotation_properties_dialog_get_author (dialog);
6469         if (ev_annotation_markup_set_label (EV_ANNOTATION_MARKUP (annot), author))
6470                 mask |= EV_ANNOTATIONS_SAVE_LABEL;
6471
6472         ev_annotation_properties_dialog_get_color (dialog, &color);
6473         if (ev_annotation_set_color (annot, &color))
6474                 mask |= EV_ANNOTATIONS_SAVE_COLOR;
6475
6476         opacity = ev_annotation_properties_dialog_get_opacity (dialog);
6477         if (ev_annotation_markup_set_opacity (EV_ANNOTATION_MARKUP (annot), opacity))
6478                 mask |= EV_ANNOTATIONS_SAVE_OPACITY;
6479
6480         popup_is_open = ev_annotation_properties_dialog_get_popup_is_open (dialog);
6481         if (ev_annotation_markup_set_popup_is_open (EV_ANNOTATION_MARKUP (annot), popup_is_open))
6482                 mask |= EV_ANNOTATIONS_SAVE_POPUP_IS_OPEN;
6483
6484         if (EV_IS_ANNOTATION_TEXT (annot)) {
6485                 EvAnnotationTextIcon icon;
6486
6487                 icon = ev_annotation_properties_dialog_get_text_icon (dialog);
6488                 if (ev_annotation_text_set_icon (EV_ANNOTATION_TEXT (annot), icon))
6489                         mask |= EV_ANNOTATIONS_SAVE_TEXT_ICON;
6490         }
6491
6492         if (mask != EV_ANNOTATIONS_SAVE_NONE) {
6493                 ev_document_doc_mutex_lock ();
6494                 ev_document_annotations_save_annotation (EV_DOCUMENT_ANNOTATIONS (window->priv->document),
6495                                                          window->priv->annot,
6496                                                          mask);
6497                 ev_document_doc_mutex_unlock ();
6498
6499                 /* FIXME: update annot region only */
6500                 ev_view_reload (EV_VIEW (window->priv->view));
6501         }
6502
6503         gtk_widget_destroy (GTK_WIDGET (dialog));
6504 }
6505
6506 static void
6507 ev_attachment_popup_cmd_open_attachment (GtkAction *action, EvWindow *window)
6508 {
6509         GList     *l;
6510         GdkScreen *screen;
6511         
6512         if (!window->priv->attach_list)
6513                 return;
6514
6515         screen = gtk_window_get_screen (GTK_WINDOW (window));
6516
6517         for (l = window->priv->attach_list; l && l->data; l = g_list_next (l)) {
6518                 EvAttachment *attachment;
6519                 GError       *error = NULL;
6520                 
6521                 attachment = (EvAttachment *) l->data;
6522                 
6523                 ev_attachment_open (attachment, screen, gtk_get_current_event_time (), &error);
6524
6525                 if (error) {
6526                         ev_window_error_message (window, error, 
6527                                                  "%s", _("Unable to open attachment"));
6528                         g_error_free (error);
6529                 }
6530         }
6531 }
6532
6533 static void
6534 attachment_save_dialog_response_cb (GtkWidget *fc,
6535                                     gint       response_id,
6536                                     EvWindow  *ev_window)
6537 {
6538         GFile                *target_file;
6539         gchar                *uri;
6540         GList                *l;
6541         GtkFileChooserAction  fc_action;
6542         gboolean              is_dir;
6543         gboolean              is_native;
6544         
6545         if (response_id != GTK_RESPONSE_OK) {
6546                 gtk_widget_destroy (fc);
6547                 return;
6548         }
6549
6550         uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (fc));
6551         target_file = g_file_new_for_uri (uri);
6552         g_object_get (G_OBJECT (fc), "action", &fc_action, NULL);
6553         is_dir = (fc_action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
6554         is_native = g_file_is_native (target_file);
6555         
6556         for (l = ev_window->priv->attach_list; l && l->data; l = g_list_next (l)) {
6557                 EvAttachment *attachment;
6558                 GFile        *save_to = NULL;
6559                 GError       *error = NULL;
6560                 
6561                 attachment = (EvAttachment *) l->data;
6562
6563                 if (is_native) {
6564                         if (is_dir) {
6565                                 save_to = g_file_get_child (target_file,
6566                                     /* FIXMEchpe: file name encoding! */
6567                                                             ev_attachment_get_name (attachment));
6568                         } else {
6569                                 save_to = g_object_ref (target_file);
6570                         }
6571                 } else {
6572                         save_to = ev_mkstemp_file ("saveattachment.XXXXXX", &error);
6573                 }
6574
6575                 if (save_to)
6576                         ev_attachment_save (attachment, save_to, &error);
6577                 
6578                 if (error) {
6579                         ev_window_error_message (ev_window, error, 
6580                                                  "%s", _("The attachment could not be saved."));
6581                         g_error_free (error);
6582                         g_object_unref (save_to);
6583
6584                         continue;
6585                 }
6586
6587                 if (!is_native) {
6588                         GFile *dest_file;
6589
6590                         if (is_dir) {
6591                                 dest_file = g_file_get_child (target_file,
6592                                                               ev_attachment_get_name (attachment));
6593                         } else {
6594                                 dest_file = g_object_ref (target_file);
6595                         }
6596
6597                         ev_window_save_remote (ev_window, EV_SAVE_ATTACHMENT,
6598                                                save_to, dest_file);
6599
6600                         g_object_unref (dest_file);
6601                 }
6602
6603                 g_object_unref (save_to);
6604         }
6605
6606         g_free (uri);
6607         g_object_unref (target_file);
6608
6609         gtk_widget_destroy (fc);
6610 }
6611
6612 static void
6613 ev_attachment_popup_cmd_save_attachment_as (GtkAction *action, EvWindow *window)
6614 {
6615         GtkWidget    *fc;
6616         EvAttachment *attachment = NULL;
6617
6618         if (!window->priv->attach_list)
6619                 return;
6620
6621         if (g_list_length (window->priv->attach_list) == 1)
6622                 attachment = (EvAttachment *) window->priv->attach_list->data;
6623         
6624         fc = gtk_file_chooser_dialog_new (
6625                 _("Save Attachment"),
6626                 GTK_WINDOW (window),
6627                 attachment ? GTK_FILE_CHOOSER_ACTION_SAVE : GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
6628                 GTK_STOCK_CANCEL,
6629                 GTK_RESPONSE_CANCEL,
6630                 GTK_STOCK_SAVE, GTK_RESPONSE_OK,
6631                 NULL);
6632
6633         gtk_dialog_set_default_response (GTK_DIALOG (fc), GTK_RESPONSE_OK);
6634         gtk_dialog_set_alternative_button_order (GTK_DIALOG (fc),
6635                                                  GTK_RESPONSE_OK,
6636                                                  GTK_RESPONSE_CANCEL,
6637                                                  -1);
6638
6639         gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (fc), TRUE);
6640         gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (fc), FALSE);
6641
6642         if (attachment)
6643                 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (fc),
6644                                                    ev_attachment_get_name (attachment));
6645
6646         g_signal_connect (fc, "response",
6647                           G_CALLBACK (attachment_save_dialog_response_cb),
6648                           window);
6649
6650         gtk_widget_show (fc);
6651 }
6652
6653 static void
6654 ev_window_media_player_key_pressed (EvWindow    *window,
6655                                     const gchar *key,
6656                                     gpointer     user_data)
6657 {
6658         if (!gtk_window_is_active (GTK_WINDOW (window))) 
6659                 return;
6660         
6661         /* Note how Previous/Next only go to the
6662          * next/previous page despite their icon telling you
6663          * they should go to the beginning/end.
6664          *
6665          * There's very few keyboards with FFW/RWD though,
6666          * so we stick the most useful keybinding on the most
6667          * often seen keys
6668          */
6669         if (strcmp (key, "Play") == 0) {
6670                 ev_window_run_presentation (window);
6671         } else if (strcmp (key, "Previous") == 0) {
6672                 ev_window_cmd_go_previous_page (NULL, window);
6673         } else if (strcmp (key, "Next") == 0) {
6674                 ev_window_cmd_go_next_page (NULL, window);
6675         } else if (strcmp (key, "FastForward") == 0) {
6676                 ev_window_cmd_go_last_page (NULL, window);
6677         } else if (strcmp (key, "Rewind") == 0) {
6678                 ev_window_cmd_go_first_page (NULL, window);
6679         }
6680 }
6681
6682 static EggToolbarsModel *
6683 get_toolbars_model (void)
6684 {
6685         EggToolbarsModel *toolbars_model;
6686         gchar            *toolbars_file;
6687         gchar            *toolbars_path;
6688         gint              i;
6689
6690         toolbars_model = egg_toolbars_model_new ();
6691
6692         toolbars_file = g_build_filename (ev_application_get_dot_dir (EV_APP, FALSE),
6693                                           "evince_toolbar.xml", NULL);
6694         toolbars_path = g_build_filename (ev_application_get_data_dir (EV_APP),
6695                                          "evince-toolbar.xml", NULL);
6696         egg_toolbars_model_load_names (toolbars_model, toolbars_path);
6697
6698         if (!egg_toolbars_model_load_toolbars (toolbars_model, toolbars_file)) {
6699                 egg_toolbars_model_load_toolbars (toolbars_model, toolbars_path);
6700                 goto skip_conversion;
6701         }
6702
6703         /* Open item doesn't exist anymore,
6704          * convert it to OpenRecent for compatibility
6705          */
6706         for (i = 0; i < egg_toolbars_model_n_items (toolbars_model, 0); i++) {
6707                 const gchar *item;
6708
6709                 item = egg_toolbars_model_item_nth (toolbars_model, 0, i);
6710                 if (g_ascii_strcasecmp (item, "FileOpen") == 0) {
6711                         egg_toolbars_model_remove_item (toolbars_model, 0, i);
6712                         egg_toolbars_model_add_item (toolbars_model, 0, i,
6713                                                      "FileOpenRecent");
6714                         egg_toolbars_model_save_toolbars (toolbars_model, toolbars_file, "1.0");
6715                         break;
6716                 }
6717         }
6718
6719     skip_conversion:
6720         g_free (toolbars_file);
6721         g_free (toolbars_path);
6722
6723         egg_toolbars_model_set_flags (toolbars_model, 0, EGG_TB_MODEL_NOT_REMOVABLE);
6724
6725         return toolbars_model;
6726 }
6727
6728 #ifdef ENABLE_DBUS
6729 static void
6730 ev_window_sync_source (EvWindow     *window,
6731                        EvSourceLink *link)
6732 {
6733         GDBusConnection *connection;
6734         GError          *error = NULL;
6735         guint32          timestamp;
6736         gchar           *uri_input;
6737         GFile           *input_gfile;
6738
6739         if (window->priv->dbus_object_id <= 0)
6740                 return;
6741
6742         connection = ev_application_get_dbus_connection (EV_APP);
6743         if (!connection)
6744                 return;
6745
6746         timestamp = gtk_get_current_event_time ();
6747         if (g_path_is_absolute (link->filename)) {
6748                 input_gfile = g_file_new_for_path (link->filename);
6749         } else {
6750                 GFile *gfile, *parent_gfile;
6751
6752                 gfile = g_file_new_for_uri (window->priv->uri);
6753                 parent_gfile = g_file_get_parent (gfile);
6754
6755                 /* parent_gfile should never be NULL */
6756                 if (parent_gfile == NULL) {
6757                         g_printerr ("Document URI is '/'\n");
6758                         return;
6759                 }
6760
6761                 input_gfile = g_file_get_child (parent_gfile, link->filename);
6762                 g_object_unref (parent_gfile);
6763                 g_object_unref (gfile);
6764         }
6765
6766         uri_input = g_file_get_uri (input_gfile);
6767         g_object_unref (input_gfile);
6768
6769         g_dbus_connection_emit_signal (connection,
6770                                        NULL,
6771                                        window->priv->dbus_object_path,
6772                                        EV_WINDOW_DBUS_INTERFACE,
6773                                        "SyncSource",
6774                                        g_variant_new ("(s(ii)u)",
6775                                                       uri_input,
6776                                                       link->line,
6777                                                       link->col,
6778                                                       timestamp),
6779                                        &error);
6780         g_free (uri_input);
6781         if (error) {
6782                 g_printerr ("Failed to emit DBus signal SyncSource: %s\n",
6783                             error->message);
6784                 g_error_free (error);
6785         }
6786 }
6787
6788 static void
6789 ev_window_emit_closed (EvWindow *window)
6790 {
6791         GDBusConnection *connection;
6792         GError          *error = NULL;
6793
6794         if (window->priv->dbus_object_id <= 0)
6795                 return;
6796
6797         connection = ev_application_get_dbus_connection (EV_APP);
6798         if (!connection)
6799                 return;
6800
6801         g_dbus_connection_emit_signal (connection,
6802                                        NULL,
6803                                        window->priv->dbus_object_path,
6804                                        EV_WINDOW_DBUS_INTERFACE,
6805                                        "Closed",
6806                                        NULL,
6807                                        &error);
6808         if (error) {
6809                 g_printerr ("Failed to emit DBus signal Closed: %s\n",
6810                             error->message);
6811                 g_error_free (error);
6812
6813                 return;
6814         }
6815
6816         /* If this is the last window call g_dbus_connection_flush_sync()
6817          * to make sure the signal is emitted.
6818          */
6819         if (ev_application_get_n_windows (EV_APP) == 1)
6820                 g_dbus_connection_flush_sync (connection, NULL, NULL);
6821 }
6822
6823 static void
6824 ev_window_emit_doc_loaded (EvWindow *window)
6825 {
6826         GDBusConnection *connection;
6827         GError          *error = NULL;
6828
6829         if (window->priv->dbus_object_id <= 0)
6830                 return;
6831
6832         connection = ev_application_get_dbus_connection (EV_APP);
6833         if (!connection)
6834                 return;
6835
6836         g_dbus_connection_emit_signal (connection,
6837                                        NULL,
6838                                        window->priv->dbus_object_path,
6839                                        EV_WINDOW_DBUS_INTERFACE,
6840                                        "DocumentLoaded",
6841                                        g_variant_new("(s)", window->priv->uri),
6842                                        &error);
6843         if (error) {
6844                 g_printerr ("Failed to emit DBus signal DocumentLoaded: %s\n",
6845                             error->message);
6846                 g_error_free (error);
6847
6848                 return;
6849         }
6850 }
6851
6852 static void
6853 method_call_cb (GDBusConnection       *connection,
6854                 const gchar           *sender,
6855                 const gchar           *object_path,
6856                 const gchar           *interface_name,
6857                 const gchar           *method_name,
6858                 GVariant              *parameters,
6859                 GDBusMethodInvocation *invocation,
6860                 gpointer               user_data)
6861 {
6862         EvWindow *window = EV_WINDOW (user_data);
6863
6864         if (g_strcmp0 (method_name, "SyncView") != 0)
6865                 return;
6866
6867         if (window->priv->document && ev_document_has_synctex (window->priv->document)) {
6868                 EvSourceLink link;
6869                 guint32      timestamp;
6870
6871                 g_variant_get (parameters, "(&s(ii)u)", &link.filename, &link.line, &link.col, &timestamp);
6872                 ev_view_highlight_forward_search (EV_VIEW (window->priv->view), &link);
6873                 gtk_window_present_with_time (GTK_WINDOW (window), timestamp);
6874         }
6875
6876         g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
6877 }
6878
6879 static const char introspection_xml[] =
6880         "<node>"
6881           "<interface name='org.gnome.evince.Window'>"
6882             "<method name='SyncView'>"
6883               "<arg type='s' name='source_file' direction='in'/>"
6884               "<arg type='(ii)' name='source_point' direction='in'/>"
6885               "<arg type='u' name='timestamp' direction='in'/>"
6886             "</method>"
6887             "<signal name='SyncSource'>"
6888               "<arg type='s' name='source_file' direction='out'/>"
6889               "<arg type='(ii)' name='source_point' direction='out'/>"
6890               "<arg type='u' name='timestamp' direction='out'/>"
6891             "</signal>"
6892             "<signal name='Closed'/>"
6893             "<signal name='DocumentLoaded'>"
6894               "<arg type='s' name='uri' direction='out'/>"
6895             "</signal>"
6896           "</interface>"
6897         "</node>";
6898
6899 static const GDBusInterfaceVTable interface_vtable = {
6900         method_call_cb,
6901         NULL,
6902         NULL
6903 };
6904
6905 static GDBusNodeInfo *introspection_data;
6906 #endif /* ENABLE_DBUS */
6907
6908 static void
6909 ev_window_init (EvWindow *ev_window)
6910 {
6911         GtkActionGroup *action_group;
6912         GtkAccelGroup *accel_group;
6913         GError *error = NULL;
6914         GtkWidget *sidebar_widget;
6915         GtkWidget *menuitem;
6916         EggToolbarsModel *toolbars_model;
6917         GObject *mpkeys;
6918         gchar *ui_path;
6919 #ifdef ENABLE_DBUS
6920         GDBusConnection *connection;
6921         static gint window_id = 0;
6922 #endif
6923
6924         g_signal_connect (ev_window, "configure_event",
6925                           G_CALLBACK (window_configure_event_cb), NULL);
6926         g_signal_connect (ev_window, "window_state_event",
6927                           G_CALLBACK (window_state_event_cb), NULL);
6928
6929         ev_window->priv = EV_WINDOW_GET_PRIVATE (ev_window);
6930
6931 #ifdef ENABLE_DBUS
6932         connection = ev_application_get_dbus_connection (EV_APP);
6933         if (connection) {
6934                 if (!introspection_data) {
6935                         introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, &error);
6936                         if (error) g_warning ("%s\n", error->message);
6937                 }
6938                 g_assert (introspection_data != NULL);
6939
6940                 ev_window->priv->dbus_object_path = g_strdup_printf (EV_WINDOW_DBUS_OBJECT_PATH, window_id++);
6941                 ev_window->priv->dbus_object_id =
6942                     g_dbus_connection_register_object (connection,
6943                                                        ev_window->priv->dbus_object_path,
6944                                                        introspection_data->interfaces[0],
6945                                                        &interface_vtable,
6946                                                        ev_window, NULL,
6947                                                        &error);
6948                 if (ev_window->priv->dbus_object_id == 0) {
6949                         g_printerr ("Failed to register bus object %s: %s\n",
6950                                     ev_window->priv->dbus_object_path, error->message);
6951                         g_error_free (error);
6952                         g_free (ev_window->priv->dbus_object_path);
6953                         ev_window->priv->dbus_object_path = NULL;
6954                         error = NULL;
6955                 }
6956         }
6957
6958 #endif /* ENABLE_DBUS */
6959
6960         ev_window->priv->model = ev_document_model_new ();
6961
6962         ev_window->priv->page_mode = PAGE_MODE_DOCUMENT;
6963         ev_window->priv->title = ev_window_title_new (ev_window);
6964
6965         ev_window->priv->main_box = gtk_vbox_new (FALSE, 0);
6966         gtk_container_add (GTK_CONTAINER (ev_window), ev_window->priv->main_box);
6967         gtk_widget_show (ev_window->priv->main_box);
6968
6969         action_group = gtk_action_group_new ("MenuActions");
6970         ev_window->priv->action_group = action_group;
6971         gtk_action_group_set_translation_domain (action_group, NULL);
6972         gtk_action_group_add_actions (action_group, entries,
6973                                       G_N_ELEMENTS (entries), ev_window);
6974         gtk_action_group_add_toggle_actions (action_group, toggle_entries,
6975                                              G_N_ELEMENTS (toggle_entries),
6976                                              ev_window);
6977         set_action_properties (action_group);
6978         register_custom_actions (ev_window, action_group);
6979
6980         ev_window->priv->ui_manager = gtk_ui_manager_new ();
6981         gtk_ui_manager_insert_action_group (ev_window->priv->ui_manager,
6982                                             action_group, 0);
6983
6984         accel_group =
6985                 gtk_ui_manager_get_accel_group (ev_window->priv->ui_manager);
6986         gtk_window_add_accel_group (GTK_WINDOW (ev_window), accel_group);
6987
6988         ev_window_set_view_accels_sensitivity (ev_window, FALSE);
6989
6990         action_group = gtk_action_group_new ("ViewPopupActions");
6991         ev_window->priv->view_popup_action_group = action_group;
6992         gtk_action_group_set_translation_domain (action_group, NULL);
6993         gtk_action_group_add_actions (action_group, view_popup_entries,
6994                                       G_N_ELEMENTS (view_popup_entries),
6995                                       ev_window);
6996         gtk_ui_manager_insert_action_group (ev_window->priv->ui_manager,
6997                                             action_group, 0);
6998
6999         action_group = gtk_action_group_new ("AttachmentPopupActions");
7000         ev_window->priv->attachment_popup_action_group = action_group;
7001         gtk_action_group_set_translation_domain (action_group, NULL);
7002         gtk_action_group_add_actions (action_group, attachment_popup_entries,
7003                                       G_N_ELEMENTS (attachment_popup_entries),
7004                                       ev_window);
7005         gtk_ui_manager_insert_action_group (ev_window->priv->ui_manager,
7006                                             action_group, 0);
7007
7008         ui_path = g_build_filename (ev_application_get_data_dir (EV_APP),
7009                                     "evince-ui.xml", NULL);
7010         if (!gtk_ui_manager_add_ui_from_file (
7011                 ev_window->priv->ui_manager, ui_path, &error))
7012         {
7013                 g_warning ("building menus failed: %s", error->message);
7014                 g_error_free (error);
7015         }
7016         g_free (ui_path);
7017
7018         ev_window->priv->recent_manager = gtk_recent_manager_get_default ();
7019         ev_window->priv->recent_action_group = NULL;
7020         ev_window->priv->recent_ui_id = 0;
7021         g_signal_connect_swapped (ev_window->priv->recent_manager,
7022                                   "changed",
7023                                   G_CALLBACK (ev_window_setup_recent),
7024                                   ev_window);
7025
7026         ev_window->priv->menubar =
7027                  gtk_ui_manager_get_widget (ev_window->priv->ui_manager,
7028                                             "/MainMenu");
7029         gtk_box_pack_start (GTK_BOX (ev_window->priv->main_box),
7030                             ev_window->priv->menubar,
7031                             FALSE, FALSE, 0);
7032         menuitem = gtk_ui_manager_get_widget (ev_window->priv->ui_manager,
7033                                               "/MainMenu/EditMenu/EditRotateLeftMenu");
7034         gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
7035         menuitem = gtk_ui_manager_get_widget (ev_window->priv->ui_manager,
7036                                               "/MainMenu/EditMenu/EditRotateRightMenu");
7037         gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
7038
7039         toolbars_model = get_toolbars_model ();
7040         ev_window->priv->toolbar = GTK_WIDGET
7041                 (g_object_new (EGG_TYPE_EDITABLE_TOOLBAR,
7042                                "ui-manager", ev_window->priv->ui_manager,
7043                                "popup-path", "/ToolbarPopup",
7044                                "model", toolbars_model,
7045                                NULL));
7046         g_object_unref (toolbars_model);
7047
7048         egg_editable_toolbar_show (EGG_EDITABLE_TOOLBAR (ev_window->priv->toolbar),
7049                                    "DefaultToolBar");
7050         gtk_box_pack_start (GTK_BOX (ev_window->priv->main_box),
7051                             ev_window->priv->toolbar,
7052                             FALSE, FALSE, 0);
7053         gtk_widget_show (ev_window->priv->toolbar);
7054
7055         /* Add the main area */
7056         ev_window->priv->hpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
7057         g_signal_connect (ev_window->priv->hpaned,
7058                           "notify::position",
7059                           G_CALLBACK (ev_window_sidebar_position_change_cb),
7060                           ev_window);
7061         
7062         gtk_paned_set_position (GTK_PANED (ev_window->priv->hpaned), SIDEBAR_DEFAULT_SIZE);
7063         gtk_box_pack_start (GTK_BOX (ev_window->priv->main_box), ev_window->priv->hpaned,
7064                             TRUE, TRUE, 0);
7065         gtk_widget_show (ev_window->priv->hpaned);
7066         
7067         ev_window->priv->sidebar = ev_sidebar_new ();
7068         ev_sidebar_set_model (EV_SIDEBAR (ev_window->priv->sidebar),
7069                               ev_window->priv->model);
7070         gtk_paned_pack1 (GTK_PANED (ev_window->priv->hpaned),
7071                          ev_window->priv->sidebar, FALSE, FALSE);
7072         gtk_widget_show (ev_window->priv->sidebar);
7073
7074         /* Stub sidebar, for now */
7075
7076         sidebar_widget = ev_sidebar_thumbnails_new ();
7077         ev_window->priv->sidebar_thumbs = sidebar_widget;
7078         g_signal_connect (sidebar_widget,
7079                           "notify::main-widget",
7080                           G_CALLBACK (sidebar_page_main_widget_update_cb),
7081                           ev_window);
7082         sidebar_page_main_widget_update_cb (G_OBJECT (sidebar_widget), NULL, ev_window);
7083         gtk_widget_show (sidebar_widget);
7084         ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
7085                              sidebar_widget);
7086
7087         sidebar_widget = ev_sidebar_links_new ();
7088         ev_window->priv->sidebar_links = sidebar_widget;
7089         g_signal_connect (sidebar_widget,
7090                           "notify::model",
7091                           G_CALLBACK (sidebar_widget_model_set),
7092                           ev_window);
7093         g_signal_connect (sidebar_widget,
7094                           "link_activated",
7095                           G_CALLBACK (sidebar_links_link_activated_cb),
7096                           ev_window);
7097         sidebar_page_main_widget_update_cb (G_OBJECT (sidebar_widget), NULL, ev_window);
7098         gtk_widget_show (sidebar_widget);
7099         ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
7100                              sidebar_widget);
7101
7102         sidebar_widget = ev_sidebar_attachments_new ();
7103         ev_window->priv->sidebar_attachments = sidebar_widget;
7104         g_signal_connect_object (sidebar_widget,
7105                                  "popup",
7106                                  G_CALLBACK (attachment_bar_menu_popup_cb),
7107                                  ev_window, 0);
7108         gtk_widget_show (sidebar_widget);
7109         ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
7110                              sidebar_widget);
7111
7112         sidebar_widget = ev_sidebar_layers_new ();
7113         ev_window->priv->sidebar_layers = sidebar_widget;
7114         g_signal_connect (sidebar_widget,
7115                           "layers_visibility_changed",
7116                           G_CALLBACK (sidebar_layers_visibility_changed),
7117                           ev_window);
7118         gtk_widget_show (sidebar_widget);
7119         ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
7120                              sidebar_widget);
7121
7122         sidebar_widget = ev_sidebar_annotations_new ();
7123         ev_window->priv->sidebar_annots = sidebar_widget;
7124         g_signal_connect (sidebar_widget,
7125                           "annot_activated",
7126                           G_CALLBACK (sidebar_annots_annot_activated_cb),
7127                           ev_window);
7128         g_signal_connect (sidebar_widget,
7129                           "begin_annot_add",
7130                           G_CALLBACK (sidebar_annots_begin_annot_add),
7131                           ev_window);
7132         g_signal_connect (sidebar_widget,
7133                           "annot_add_cancelled",
7134                           G_CALLBACK (sidebar_annots_annot_add_cancelled),
7135                           ev_window);
7136         gtk_widget_show (sidebar_widget);
7137         ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
7138                              sidebar_widget);
7139
7140         ev_window->priv->view_box = gtk_vbox_new (FALSE, 0);
7141         ev_window->priv->scrolled_window =
7142                 GTK_WIDGET (g_object_new (GTK_TYPE_SCROLLED_WINDOW,
7143                                           "shadow-type", GTK_SHADOW_IN,
7144                                           NULL));
7145         gtk_box_pack_start (GTK_BOX (ev_window->priv->view_box),
7146                             ev_window->priv->scrolled_window,
7147                             TRUE, TRUE, 0);
7148         gtk_widget_show (ev_window->priv->scrolled_window);
7149
7150         gtk_paned_add2 (GTK_PANED (ev_window->priv->hpaned),
7151                         ev_window->priv->view_box);
7152         gtk_widget_show (ev_window->priv->view_box);
7153
7154         ev_window->priv->view = ev_view_new ();
7155         ev_view_set_page_cache_size (EV_VIEW (ev_window->priv->view), PAGE_CACHE_SIZE);
7156         ev_view_set_model (EV_VIEW (ev_window->priv->view), ev_window->priv->model);
7157
7158         ev_window->priv->password_view = ev_password_view_new (GTK_WINDOW (ev_window));
7159         g_signal_connect_swapped (ev_window->priv->password_view,
7160                                   "unlock",
7161                                   G_CALLBACK (ev_window_password_view_unlock),
7162                                   ev_window);
7163         g_signal_connect_object (ev_window->priv->view, "focus_in_event",
7164                                  G_CALLBACK (view_actions_focus_in_cb),
7165                                  ev_window, 0);
7166         g_signal_connect_object (ev_window->priv->view, "focus_out_event",
7167                                  G_CALLBACK (view_actions_focus_out_cb),
7168                                  ev_window, 0);
7169         g_signal_connect_object (ev_window->priv->view, "external-link",
7170                                  G_CALLBACK (view_external_link_cb),
7171                                  ev_window, 0);
7172         g_signal_connect_object (ev_window->priv->view, "handle-link",
7173                                  G_CALLBACK (view_handle_link_cb),
7174                                  ev_window, 0);
7175         g_signal_connect_object (ev_window->priv->view, "popup",
7176                                  G_CALLBACK (view_menu_popup_cb),
7177                                  ev_window, 0);
7178         g_signal_connect_object (ev_window->priv->view, "selection-changed",
7179                                  G_CALLBACK (view_selection_changed_cb),
7180                                  ev_window, 0);
7181         g_signal_connect_object (ev_window->priv->view, "annot-added",
7182                                  G_CALLBACK (view_annot_added),
7183                                  ev_window, 0);
7184         g_signal_connect_object (ev_window->priv->view, "layers-changed",
7185                                  G_CALLBACK (view_layers_changed_cb),
7186                                  ev_window, 0);
7187 #ifdef ENABLE_DBUS
7188         g_signal_connect_swapped (ev_window->priv->view, "sync-source",
7189                                   G_CALLBACK (ev_window_sync_source),
7190                                   ev_window);
7191 #endif
7192         gtk_widget_show (ev_window->priv->view);
7193         gtk_widget_show (ev_window->priv->password_view);
7194
7195         /* Find Bar */
7196         ev_window->priv->find_bar = egg_find_bar_new ();
7197         gtk_box_pack_end (GTK_BOX (ev_window->priv->main_box),
7198                           ev_window->priv->find_bar,
7199                           FALSE, TRUE, 0);
7200
7201         /* We own a ref on these widgets, as we can swap them in and out */
7202         g_object_ref (ev_window->priv->view);
7203         g_object_ref (ev_window->priv->password_view);
7204
7205         gtk_container_add (GTK_CONTAINER (ev_window->priv->scrolled_window),
7206                            ev_window->priv->view);
7207
7208         /* Connect to model signals */
7209         g_signal_connect_swapped (ev_window->priv->model,
7210                                   "page-changed",
7211                                   G_CALLBACK (ev_window_page_changed_cb),
7212                                   ev_window);
7213         g_signal_connect (ev_window->priv->model,
7214                           "notify::document",
7215                           G_CALLBACK (ev_window_document_changed_cb),
7216                           ev_window);
7217         g_signal_connect (ev_window->priv->model,
7218                           "notify::scale",
7219                           G_CALLBACK (ev_window_zoom_changed_cb),
7220                           ev_window);
7221         g_signal_connect (ev_window->priv->model,
7222                           "notify::sizing-mode",
7223                           G_CALLBACK (ev_window_sizing_mode_changed_cb),
7224                           ev_window);
7225         g_signal_connect (ev_window->priv->model,
7226                           "notify::rotation",
7227                           G_CALLBACK (ev_window_rotation_changed_cb),
7228                           ev_window);
7229         g_signal_connect (ev_window->priv->model,
7230                           "notify::continuous",
7231                           G_CALLBACK (ev_window_continuous_changed_cb),
7232                           ev_window);
7233         g_signal_connect (ev_window->priv->model,
7234                           "notify::dual-page",
7235                           G_CALLBACK (ev_window_dual_mode_changed_cb),
7236                           ev_window);
7237         g_signal_connect (ev_window->priv->model,
7238                           "notify::inverted-colors",
7239                           G_CALLBACK (ev_window_inverted_colors_changed_cb),
7240                           ev_window);
7241
7242         /* Connect sidebar signals */
7243         g_signal_connect (ev_window->priv->sidebar,
7244                           "notify::visible",
7245                           G_CALLBACK (ev_window_sidebar_visibility_changed_cb),
7246                           ev_window);
7247         g_signal_connect (ev_window->priv->sidebar,
7248                           "notify::current-page",
7249                           G_CALLBACK (ev_window_sidebar_current_page_changed_cb),
7250                           ev_window);
7251
7252         /* Connect to find bar signals */
7253         g_signal_connect (ev_window->priv->find_bar,
7254                           "previous",
7255                           G_CALLBACK (find_bar_previous_cb),
7256                           ev_window);
7257         g_signal_connect (ev_window->priv->find_bar,
7258                           "next",
7259                           G_CALLBACK (find_bar_next_cb),
7260                           ev_window);
7261         g_signal_connect (ev_window->priv->find_bar,
7262                           "close",
7263                           G_CALLBACK (find_bar_close_cb),
7264                           ev_window);
7265         g_signal_connect (ev_window->priv->find_bar,
7266                           "notify::search-string",
7267                           G_CALLBACK (find_bar_search_changed_cb),
7268                           ev_window);
7269         g_signal_connect (ev_window->priv->find_bar,
7270                           "notify::case-sensitive",
7271                           G_CALLBACK (find_bar_search_changed_cb),
7272                           ev_window);
7273         g_signal_connect (ev_window->priv->find_bar,
7274                           "notify::visible",
7275                           G_CALLBACK (find_bar_visibility_changed_cb),
7276                           ev_window);
7277         g_signal_connect (ev_window->priv->find_bar,
7278                           "scroll",
7279                           G_CALLBACK (find_bar_scroll),
7280                           ev_window);
7281
7282         /* Popups */
7283         ev_window->priv->view_popup = gtk_ui_manager_get_widget (ev_window->priv->ui_manager,
7284                                                                  "/DocumentPopup");
7285         ev_window->priv->link = NULL;
7286
7287         ev_window->priv->attachment_popup = gtk_ui_manager_get_widget (ev_window->priv->ui_manager,
7288                                                                        "/AttachmentPopup");
7289         ev_window->priv->attach_list = NULL;
7290
7291         /* Media player keys */
7292         mpkeys = ev_application_get_media_keys (EV_APP);
7293         if (mpkeys) {
7294                 g_signal_connect_swapped (mpkeys, "key_pressed",
7295                                           G_CALLBACK (ev_window_media_player_key_pressed),
7296                                           ev_window);
7297         }
7298
7299         /* Give focus to the document view */
7300         gtk_widget_grab_focus (ev_window->priv->view);
7301
7302         ev_window->priv->default_settings = g_settings_new (GS_SCHEMA_NAME".Default");
7303         g_settings_delay (ev_window->priv->default_settings);
7304
7305         /* Set it user interface params */
7306         ev_window_setup_recent (ev_window);
7307
7308         ev_window_setup_gtk_settings (ev_window);
7309
7310         setup_chrome_from_metadata (ev_window);
7311         update_chrome_actions (ev_window);
7312         update_chrome_visibility (ev_window);
7313
7314         gtk_window_set_default_size (GTK_WINDOW (ev_window), 600, 600);
7315
7316         setup_view_from_metadata (ev_window);
7317         setup_sidebar_from_metadata (ev_window);
7318
7319         ev_window_sizing_mode_changed_cb (ev_window->priv->model, NULL, ev_window);
7320         ev_window_setup_action_sensitivity (ev_window);
7321
7322         /* Drag and Drop */
7323         gtk_drag_dest_set (GTK_WIDGET (ev_window),
7324                            GTK_DEST_DEFAULT_ALL,
7325                            NULL, 0,
7326                            GDK_ACTION_COPY);
7327         gtk_drag_dest_add_uri_targets (GTK_WIDGET (ev_window));
7328 }
7329
7330 /**
7331  * ev_window_new:
7332  *
7333  * Creates a #GtkWidget that represents the window.
7334  *
7335  * Returns: the #GtkWidget that represents the window.
7336  */
7337 GtkWidget *
7338 ev_window_new (void)
7339 {
7340         GtkWidget *ev_window;
7341
7342         ev_window = GTK_WIDGET (g_object_new (EV_TYPE_WINDOW,
7343                                               "type", GTK_WINDOW_TOPLEVEL,
7344                                               NULL));
7345
7346         return ev_window;
7347 }
7348
7349 const gchar *
7350 ev_window_get_dbus_object_path (EvWindow *ev_window)
7351 {
7352 #ifdef ENABLE_DBUS
7353         return ev_window->priv->dbus_object_path;
7354 #else
7355         return NULL;
7356 #endif
7357 }