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