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