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