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