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