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