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