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