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