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